1. 程式人生 > 其它 >【走近Spring】控制Spring IoC容器對Bean(含@Configuration配置類)的載入順序(@DependsOn註解的使用)

【走近Spring】控制Spring IoC容器對Bean(含@Configuration配置類)的載入順序(@DependsOn註解的使用)

為什麼要控制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 初始化。。。