1.什么是Bean的循環依賴?
? ? ? ? 簡單來說就是在A類中,初始化A時需要用到B對象,而在B類中,初始化B時需要用到A對象,這種狀況下在Spring中,如果A和B同時初始化,A,B同時都需要對方的資源,就會僵持不下。這也就是Spring中的循環依賴問題。Spring框架對這種屬性所產生的循環依賴的解決辦法很簡單,就是使用@Autowired注解,如下:
public class BeanA {@Autowiredprivate BeanB beanB;
}public class BeanB {@Autowiredprivate BeanA beanA;
}
? ? ? ? 對于構造方法的循環依賴,Spring可采用@Lazy或者使用Setter()方法去解決,這里我們不做討論。
2.@Autowired
? ? ? ? 在Spring中,我們可以使用@Autowired注解對屬性或者方法參數進行標注,會從IOC容器中拿到對應的實例自動注入。
3.解決循環依賴的具體細節
? ? ? ? 首先,Spring中內部有三大緩存,在 DefaultSingletonBeanRegistry 類中定義了 3 個 Map 對象充當緩存。分別是:
- singletonObjects:一級緩存,用于保存實例化,初始化完成之后的Bean實例,ConcurrentHashMap存儲,線程安全。
- earlysingletonObjects:二級緩存,用于保存實例化完成,還未初始化完的Bean實例,屬于提前暴露。
- singleFactories:三級緩存,存放生成Bean的工廠,也相當是存放了獲取B
ean
的一個回調方式。
? ? ? ? 具體實現:
先把創建A的工廠,存入到三級緩存中,之后A進行實例化,實例化之后需要屬性賦值B,?然后再一級、二級、三級緩存中找B,如果都沒有,將創建B的工廠存入到三級緩存,之后B進行實例化,B實例化后需要屬性賦值A,所以就去三級緩存中利用創建A的工廠回調拿到A,之后B的屬性賦值完畢,然后將拿到的A存放到二級緩存中,并刪除三級緩存中A的工廠,等到B整體初始化完畢,將B放入一級緩存,然后A的屬性賦值B也完成,等到A整體初始化完畢,則將A存放到一級緩存中,并刪除二級緩存的A。
????????