Spring inject a bean into another bean - java

I am trying to inject a bean into another bean that uses it. How can I do this?
public class MySpringConfig{
#Bean
public MyObject getMyObject() {
//.....
return MyObjectInstance;
}
#Bean
public SomeObject getSomeObject(MyObject myObject) {
//.....
return SomeObjectInstance;
}
}

I think you can do this with this way, this is working in my project.
#Configuration
public class AppConfig {
#Bean
public Bean1 foo(#Qualifier("bean2") Bean2 bean2) {
return new Bean1(bean2);
}
}

i think that might work!
#Configuration
public class AppConfig {
#Bean
public Bean2 bean2() {
return new Bean2();
}
#Bean
#DependsOn({"bean2"})
public Bean1 foo(#Autowired Bean2 bean2) {
return new Bean1(bean2); // or your can write new Bean1(bean2());
}
}

Parameters don't work exactly in the same way in #Bean and #Component.
For a class annotated with #Component, specifying them is required for the autowired constructor but in a #Bean declaration you don't need to provide a parameter to specify the MyObject dependency to use (while it will work) if that is accessible in the current class, which is your case.
So you want to inject directly the bean by invoking getMyObject() in the #Bean definition.
For example to pass it a constructor arg :
#Bean
public SomeObject getSomeObject() {
//....
// you injected MyObject in the current bean to create
SomeObject object = new SomeObject(getMyObject());
//...
return SomeObjectInstance;
}
And don't forget to annotate the class with #Configuration to make it considered by Spring.

Related

Provide single #Bean that can be used to inject in multiple interfaces

Consider the following piece of code
public interface Iface1 { }
public interface Iface2 { }
public class A implements Iface1, Iface2 {
}
#Configuration
public class AutoConfig {
#Bean
Iface1 provideIface1Impl() {
return new A(); // instance no 1234
}
#Bean
#ConditionalOnBean(A.class)
#Autowired
Iface2 provideIface2Impl(A aImpl) {
return aImpl;
}
}
I would like the second #Bean method to be autowired with the instance from the first one (1234) and I'd like the second #Bean method to return the same instance, so that I can use the same instance for clients of Iface1 and Iface2.
Current problem is that spring doesn't run the second #Bean because there is no #Bean of type A.class - the created bean is considered as Iface1 even though it is of type A.
Just define bean A. When injecting IFace1 and Iface2 they will automatically resolve to A (if A is the only implementation of course).
#Bean
public A a() {
return new A();
}
I think you should try to define only one #Bean. It will create a singleton:
#Bean
public A a() {
return new A();
}
Then just use the name of this bean in #Qualifier annotation:
#Autowired
#Qualifier("a")
private Iface1 iface1;
#Autowired
#Qualifier("a")
private Iface2 iface2;
Additionally to what others have answered, I'd like to cover that part of the question that touches bean's dependencies.
To inject a dependency to a #Bean-annotated method, there are two ways:
Call another #Bean-method directly
Add parameter to the method
Examples of both:
#Configuration
public class AppConfig {
#Bean
public Foo foo() {
return new Foo();
}
#Bean
public Bar bar() {
return new Bar(foo());
}
#Bean
public Baz baz(Foo foo) {
return new Baz(foo);
}
}
So your provideIface2Impl could look like this:
#Bean
Iface2 provideIface2Impl(A aImpl) {
return aImpl;
}
// or...
#Bean
Iface2 provideIface2Impl() {
return (Iface2)provideIface1Impl();
}
But don't use it this way, it will lead to subtle bugs like double-proxying or "No unique bean of type" error, etc. Prefer what Gorazd suggested.

How to use multiple spring configuration files

I have a java spring configuration defined like so,
#Configuration
public class FirstConfiguration {
#Bean
FirstController firstController() {
return new FirstController(firstService());
}
#Bean
FirstService firstService() {
return new FirstServiceImpl(secondService());
}
}
Now the beans in this configuration depend on SecondConfiguration defined like so,
#Configuration
public class SecondConfiguration {
#Bean
SecondController SecondController() {
return new SecondController(SecondService());
}
#Bean
SecondService secondService() {
return new SecondServiceImpl();
}
}
How can I make use of the secondService() bean in my FirstConfiguration?
Since the SecondService is a bean, you could inject it into the firstService method to configure another bean:
#Bean
FirstService firstService(#Autowired SecondService secondService) {
return new FirstServiceImpl(secondService);
}
You can inject the firstService like this :
#Autowired
SecondService secondService
You can refer the method secondService() directly when you import the configuration.
#Configuration
#Import(SecondConfiguration.class)
public class FirstConfiguration {
#Bean
FirstController firstController() {
return new FirstController(firstService());
}
#Bean
SomeController someController() {
return new SomeController(secondService());
}
}
Refer the Spring config import

how to autowire #bean classes

I have following #Configuration class
#Configuration
public class SomeClass {
#Bean
public BeanClass get() {
return new BeanClass()
}
}
Now I want to autowire BeanClass in some other class
public class SomeClass2 {
#Autowired
BeanClass beanCLass
}
Currently beanClass is coming null.
What and how exactly I need to tell spring for this autowiring.
According to Spring documentation
By default, the bean name will be that of the method name
get is your bean name, try with this configuration:
#Configurtion
public class SomeClass {
#Bean
public BeanClass beanCLass() {
return new BeanClass()
}
}
Bean
#Component
public class SomeClass2 {
#Autowired
BeanClass beanCLass
}
Your SomeClass2 must be a spring bean. Annotate SomeClass2 with #Component.

Spring #Profile works on class, but not on #Bean

I'm unable to get #Profile to work on a #Bean, but it works fine on the #Configuration class. In my module tests I correctly get the MyServiceStub autowired in the first example, but not in the second.
Does anyone know why?
This works:
MyConfig.java
#Configuration
#Import({StubConfig.class, RealConfig.class}
public class MyConfig {}
StubConfig.java
#Profile({"featureTest", "moduleTest"})
#Configuration
public class StubConfig {
#Bean
public MyService myService() {
return new MyServiceStub();
}
}
RealConfig.java
#Profile({"!featureTest", "!moduleTest"})
#Configuration
public class RealConfig {
#Bean
public MyService myService() {
return new MyService();
}
}
But this doesn't work:
MyConfig.java
#Configuration
public class MyConfig {
#Bean
#Profile({"featureTest", "moduleTest"})
public MyService myServiceStub() {
return new MyServiceStub();
}
#Bean
#Profile({"!featureTest", "!moduleTest"})
public MyService myService() {
return new MyService();
}
}
Instead of using #Profile approach, you could try using the #Conditional to have conditional bean creation.
Or have an explicit if-stmt to check what is the activeProfile. And you can create the Bean instance depending on the activeProfile. This approach I think would mirror what could be done in Spring XML using their expression language. But the #Conditional seems better fit for you.

Using prototype beans defined in a different java-based Spring config file

Assume we have two spring config files: ConfigA.java and ConfigB.java.
Here's how ConfigA.java may look like:
#Configuration
class ConfigA {
#Scope("prototype")
#Bean public Foo fooPrototype() {
return new Foo(params);
}
}
And now I want to inject a few instances of Foo to a number of singleton-scoped beans declared in ConfigB.java:
#Configuration
#Import(ConfigA.class)
class ConfigB {
#Bean public Bar bar() {
return new Bar(*** how to inject Foo instance here? ***);
}
#Bean public Buzz buzz() {
return new Buzz(*** how to inject Foo instance here? ***);
}
}
If I had a single configuration file, I would simply replace the blocks enclosed in asterisks with fooPrototype().
But, how to inject different Foo instances to bar() and buzz() beans provided fooPrototype() is declared in a different configuration file?
This looks similar to the example in the Spring documentation ยง5.12.5 Composing Java-based configurations.
This same page gives a solution: You can autowire the configuration beans.
#Configuration
#Import(ConfigA.class)
class ConfigB {
#Autowired ConfigA configA;
#Bean public Bar bar() {
return new Bar(configA.fooPrototype());
}
#Bean public Buzz buzz() {
return new Buzz(configA.fooPrototype());
}
}
Can't you just pass fooPrototype as a method arg? E.g.:
#Bean public Bar bar(Foo fooPrototype) {
return new Bar(fooPrototype);
}
#Bean public Buzz buzz(Foo fooPrototype) {
return new Buzz(fooPrototype);
}

Categories