spring容器載入bean順序是不肯定的,spring框架沒有約定特定順序邏輯規範。但spring保證若是A依賴B(如beanA中有@Autowired B的變量),那麼B將先於A被加載。但若是beanA不直接依賴B,咱們如何讓B仍先加載呢?spring
須要的場景距離以下數組
間接(並非直接@Autowired)
依賴 bean B。如bean A有一個屬性,須要在初始化的時候對其進行賦值(須要在初始化的時候作,是由於這個屬性實際上是包裝了其它的幾個Bean的,好比說代理了Bean B),因此這就造成了Bean A間接的依賴Bean B了以上是兩種典型的,Bean初始化的時候存在依賴關係的狀況,均可以經過@DependsOn
來解決 。app
例子框架
準備工做:(兩個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 初始化。。。"); } }
啓動容器,打印順序(初始化順序以下:)spa
HelloServiceImpl 初始化。。。 AsyncHelloController 初始化。。。 HelloController 初始化。。。
須要注意的是:這個demo的日誌都是放在默認的構造函數裏面的,所以即便你使用了@Autowired
,也是不會打亂構造函數的執行順序的,由於,由於@Autowired的解析發生在給屬性賦值的populate()方法裏,這個時候本身已經實例化了,纔會去給屬性賦值, 因此若是你要求的時機稍微比較晚能夠在賦值期間、或者實例化期間。代理
//@DependsOn // 這裏面寫String數組。不寫不會生效,可是若寫了,名字要寫正確,不然會報錯的 @DependsOn({"helloController"}) // 名稱必須寫對,必須是容器裏存在的Bean,不然啓動報錯的(fast-fail是好事) @Controller public class AsyncHelloController { ... } HelloServiceImpl 初始化。。。 HelloController 初始化。。。 --> HelloController先被實例化了~~~ AsyncHelloController 初始化。。。
使用@Lazy間接實現日誌
@Lazy public class AsyncHelloController { ... } HelloServiceImpl 初始化。。。 HelloController 初始化。。。
咱們發現它只有兩句輸出,這個時候AsyncHelloController
尚未實例化。只有首次訪問它的時候纔會實例化,因此咱們是經過間接的方式
實現了這個效果。code