【走近Spring】控制Spring IoC容器對Bean(含@Configuration配置類)的載入順序(@DependsOn註解的使用)
阿新 • • 發佈:2021-12-11
為什麼要控制Bean的載入順序?
@Order註解等並不能控制Bean的載入順序的~~因為Spring在解析Bean的時候,根本就沒有參考這個註解。另外@Configuration配置類的載入,也不會受到@Order註解的影響,它拿到配置的陣列後,僅僅就是一個for迴圈遍歷去解析。
另外需要說明的一點是:@Configuration註解的解析順序,在Spring Boot環境下會受到影響的(畢竟Boot都是自動的,而不是我們手動傳值的) 相關注解有:@AutoConfigureAfter、@AutoConfigureBefore、@AutoconfigureOrder等等
Spring容器載入bean順序是不確定的,Spring框架沒有約定特定順序邏輯規範。
但Spring能保證如果A依賴B(如beanA中有@Autowired B的變數),那麼B將先於A被載入(這屬於Spring容器內部就自動識別處理了)。但如果beanA不直接依賴B,我們如何讓B仍先載入?
需要的場景如下:
- bean A間接(並不是直接@Autowired)依賴 bean B。如bean A有一個屬性,需要在初始化的時候對其進行賦值(需要在初始化的時候做,是因為這個屬性其實是包裝了其它的幾個Bean的,比如說代理了Bean B),所以這就形成了Bean A間接的依賴Bean B了
- bean A是事件釋出者(或JMS釋出者),bean B (或一些) 負責監聽這些事件,典型的如觀察者模式。我們不想B 錯過任何事件,那麼B需要首先被初始化。
以上是兩種典型的,Bean初始化的時候存在依賴關係的情況,都可以通過@DependsOn來解決。(當然有的時候可以通過別的方式間接解決,比如特殊介面SmartInitializingSingleton ,又或者是Spring Boot提供的CommandLineRunner、ApplicationRunner等介面,但這些都不是本文研究的重點)。
Bean載入順序、依賴關係示例
這裡面解答的方案,不考慮上面說到的使用SmartInitializingSingleton等間接的方案
準備工作:(兩個controller和一個service)
@Controller public class HelloController { public HelloController() { System.out.println("HelloController 初始化。。。"); } @ResponseBody @GetMapping("/hello") public String helloGet() throws Exception { return "hello...Get"; } } @Controller public class AsyncHelloController { public AsyncHelloController() { System.out.println("AsyncHelloController 初始化。。。"); } } @Service public class HelloServiceImpl implements HelloService { public HelloServiceImpl() { System.out.println("HelloServiceImpl 初始化。。。"); } }
啟動容器,列印順序(初始化順序如下:)
HelloServiceImpl 初始化。。。
AsyncHelloController 初始化。。。
HelloController 初始化。。。