简体   繁体   中英

Spring external library beans initialization order

I've encountered a problem in my application and somehow i need to force one bean A to be initialized before another bean B. These beans are provided by external dependencies (different dependencies) so I cannot simply do it with @DependsOn annotation.
Is there any solution available?

I set up a simple (modular, maven) project and did experience no issues using @DependsOn annotation on an "external component". Only few things to accomplish:

  1. Ensure A is in the (runtime) classpath of B .
  2. Ensure B 's application context @ComponentScan s (also) A .
  3. Find out/guess the "logical bean name" of A and use that value in your @DependsOn annotation. ..then @DependsOn works as expected (also on "external dependencies").

The sample uses , but (I am sure) the configuration details are applicable to a "boot-less" environment/context.


And considering the javadoc of DependsOn:

Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization.

@Autowired would give you the same effect (with similar effort), but with type safety/without "name guessing" - I added it to the sample .


REWORK : Regarding this from a third project (baz), you have again several options to force A initialization before B .

  1. If A and B initialization is trivial (eg default constructor), you can proceed in your configuration/application like this:

     import ...A; import ...B; ... @Configuration// @SpringBootApplication ..or idempotent public class MyConfig { ... @Bean("a") public A a() { return new A(); } @Bean @DependsOn("a") public B b() { return new B(); } ... }
  2. If initialization (of A and B) is not trivial, but you can refer to existing (external) Configurations, then this works (redefining autowired beans, adding dependsOn annotation):

     @Configuration @Import(value = {BConfig.class, AConfig.class}) class MyConfig { @Bean("a") public A a(@Autowired A a) { return a; } @Bean @DependsOn("a") public B b(@Autowired B b) { return b; } }
  3. You rely on component scan, and redefine the beans (with dependsOn):

     @Configuration @ComponentScan(basePackageClasses = {B.class, A.class}) class MyConfig { // same as 2. }
  4. ...

If the external config (2., 3.) defines the beans with the same "name", then spring.main.allow-bean-definition-overriding property must be set to true (in application.properties or idempotent).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM