一、基本知識儲備
1.Spring的bean注入方式
A).構造器注入
@Service
public class BeanOne {
//注入對象BeanTwo
private BeanTwo bt;
//構造器
public BeanOne(BeanTwo bt) {
this.bt = bt ;
}
}
@Service
public class BeanTwo {
public BeanTwo(BeanOne bo) {
......
......
}
}
總結:構造器注入方式,Spring 是無法解決這種注入方式的循環依賴的,這種方式會在項目啟動時拋出異常(
BeanCurrentlyInCreationException),至於為什麼解決不了,暫且先不解釋,後面會再說明,
B).Setter方式單例注入
@Service
public class BeanOne {
//注入對象BeanTwo
private BeanTwo bt;
//一定要寫被注入對象的set方法
public void setBeanTwo(BeanTwo bt) {
this.bt = bt;
}
}
@Service
public class BeanTwo {
......
......
}
總結:此種方式也會產生循環依賴問題,但Spring 在初始化時會對其進行處理,從而解決循環依賴問題
C).singleton模式field屬性注入循環依賴(默認模式)
相信大家在寫代碼時都會用到這種寫法:
@Service
public class AServiceImpl implements AService {
@Autowired
private BService bService;
...
}
@Service
public class BServiceImpl implements BService {
@Autowired
private AService aService;
...
}
總結:屬性注入方式其實和Setter注入方式類似,Spring 在初始化bean過程中都會解決,只是兩種注入還是有所區別。
2.三種注入方式的不同
- 屬性注入不能有效指明依賴
相信很多人都遇見過一個bug,依賴注入的對象為null,在啟動依賴容器時遇到這個問題都是配置的依賴注入少了一個註解什麼的。
這種方式就過於依賴注入容器了,當沒有啟動整個依賴容器時,這個類就不能運轉,在反射時無法提供這個類需要的依賴。
依賴注入的核心思想之一就是被容器管理的類不應該依賴被容器管理的依賴,換成白話來說就是如果這個類使用了依賴注入的類,那麼這個類擺脫了這幾個依賴必須也能正常運行。然而使用變量注入的方式是不能保證這點的。
- 而如果是採用構造器注入或者set注入,就可以避免以上問題:
- 使用set方式時,這是一種選擇注入,可有可無,即使沒有注入這個依賴,那麼也不會影響整個類的運行。
- 使用構造器方式時已經顯式註明必須強制注入。通過強制指明依賴注入來保證這個類的運行
2.循環依賴
循環依賴:顧名思義,就是N個類循環(嵌套)引用。
通俗的講就是N個Bean互相引用對方,最終形成閉環。用一副經典的圖示可以表示成這樣(A、B、C都代表對象,虛線代表引用關係):

二、Spring如何解決單列循環依賴
首先,Spring內部維護了三個Map,也就是我們通常說的三級緩存。

在Spring的DefaultSingletonBeanRegistry類中,你會發現上面定義了三個Map:
- singletonObjects(一級緩存),稱「單例池」「容器」,存儲完整的單例Bean的地方。
- singletonFactories(二級緩存) 存放原始的 bean 對象(尚未填充屬性),用於解決循環依賴
- earlySingletonObjects(三級緩存) 映射Bean的早期引用,也就是說在這個Map里的Bean不是完整的,甚至還不能稱之為「Bean」,只是一個實例化Instance.
1.bean創建流程

2.關鍵代碼解析
創建bean之前先獲取bean,getSingleton()
- 先從一級緩存singletonObjects中去獲取。
- 如果獲取不到或者對象正在創建中(isSingletonCurrentlyInCreation()),那就再從二級緩存earlySingletonObjects中獲取。
- 如果還是獲取不到,且允許singletonFactories(allowEarlyReference=true)通過getObject()獲取。就從三級緩存singletonFactory.getObject()獲取。(如果獲取到了就從singletonFactories中移除,並且放進earlySingletonObjects。其實也就是從三級緩存移動到了二級緩存

未完,待續。。。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/222733.html