I have following @Configuration
class, in which I am declaring a @Bean that depends on an @Autowired
list of beans. However, this list is not complete when I am accessing to it. All @Bean
definitions been executed, except the one defined in the same class.
@Configuration
public class MyConfig {
@Autowired
List<RequiredBean> requiredBeans;
@Bean(name="ProblemHere")
public CustomObject customObject() {
log.info(requiredBeans.size()); // 1 (debugging, I can see is the one defined in "AnotherConfigClass")
}
@Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Having other classes like;
@Configuration
public class AnotherConfigClass {
@Bean(name="ThisOneGetsExecuted")
public RequiredBean reqBean() {
// this gets executed, and therefore, added to the list
return new RequiredBean();
}
}
Probably, the easiest solution would be to add @DependsOn("reqBeanInsideClass").
However:
@Bean
s defined in different classes, but not in this one.@Bean
does not get executedI guess the correct approach should be something like
@DependsOn(List<RequiredBean>) // Obviously this does not work
How should I solve this?
Update
I have copied the exact same class twice, in order to see what would happen, so now I have also:
@Configuration
public class MyConfig2 {
@Autowired
List<RequiredBean> requiredBeans;
@Bean(name="ProblemHere2")
public CustomObject customObject() {
log.info(requiredBeans.size());
}
@Bean(name="reqBeanInsideClass2")
public RequiredBean reqBean() {
// this method does not get executed
return new RequiredBean();
}
}
Amazingly, by doing this, both @Beans
methods (ProblemHere
& ProblemHere2
) are called before both reqBeanInsideClass
and reqBeanInsideClass2
methods.
For some reason I guess, Springboot is able to recognize @Beans
required for a class as long as they are defined in another class.
Can you not utilize the array input for @DependsOn
rather than passing singular value, since it accepts String[]
? That would wait for all the beans that are explicitly declared in the array before initializing, though has to be defined manually.
@Configuration
public class MyConfig {
@Autowired
List<RequiredBean> requiredBeans;
@Bean(name="customObject")
@DependsOn({"reqBeanInsideClass", "thisOneGetsExecuted"})
public CustomObject customObject() {
log.info(requiredBeans.size());
}
@Bean(name="reqBeanInsideClass")
public RequiredBean reqBean() {
return new RequiredBean();
}
}
@Autowired
list of beans will be same as a single bean of same type, it will contain all beans with that type or with that superclass via springs injection, the problem is the ordering of bean initialization is not controlled properly, @DependsOn
with array bean input should resolve this!
Or
You can make CustomObject
bean @Lazy
, so it will be initialized only when it is used within the code after initialization is done. The bean must not be used within another non-lazy bean I think. Just call some logic where an @Autowired
CustomObject
is used, it should instantiate the bean at that moment, where the list will contain all possible RequiredBean
s
@Lazy
@Bean(name="customObject")
public CustomObject customObject() {
log.info(requiredBeans.size());
}