spring是如何解決單例的循環(huán)依賴注入
首先看下面三個緩存:
1.singletonObjects:存放初始化好的bean
2.earlySingletonObjects:存放了剛實例化好的盐杂,但是還未配置屬性和初始化的bean逗载,我們在獲取該bean的時候會調用beanPostProcessor的getEarlyReference進行一些提前獲取bean的必要操作
3.singletonFactories:存放我剛實例化的bean,通過ObjectFactory链烈,可以讓如果有提前需要bean的需要可以調用該
objectfactory 其會將剛實例化好的bean經過beanPostProcessor的getEarlyReference處理進行返回
我們先實例化A厉斟,實例化好后
調用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
() -> getEarlyBeanReference(beanName, mbd, bean)是objectFactory的實現匿名類,然后此時我們設置屬性的時候會發(fā)現我們還依賴B强衡,于是我們去實例化B而當我們此時實例化B的會經過下面這個方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
首先從singletonObjects獲取是否存在以及初始化好的bean
Object singletonObject = this.singletonObjects.get(beanName);
如果沒有擦秽,且依賴的A正在初始化,那我們去嘗試看看earlySingletonObjects是否有對象
earlySingletonObjects存放的是還未實例化好對象
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
因為我們初始化bean都是加鎖的漩勤,但是這邊的鎖對于循環(huán)依賴是沒用的感挥,因為我們都是實例化好對象
準備設置屬性的時候才發(fā)現循環(huán)依賴這個時候再去創(chuàng)建依賴對象,都是同一個線程此時鎖是可重入的
synchronized (this.singletonObjects) {
從earlySingletonObjects獲取
singletonObject = this.earlySingletonObjects.get(beanName);
獲取不到 但是支持獲取EarlyReference
if (singletonObject == null && allowEarlyReference) {
我們獲取objectfactory越败,這個objectfactory就是
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
中的() -> getEarlyBeanReference(beanName, mbd, bean)触幼,然后吧結果放入
earlySingletonObjects,我們在整個單例創(chuàng)建結束的時候在把正在初始化好的對象放入
singletonObjects究飞,刪除其他緩存中的對象域蜗,具體的可以看我們創(chuàng)建單例的時候 在方法結束時候會執(zhí)行這個操作
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
由此可見 如果之前已經把A存放在singletonFactories巨双,那么B會把其調出來放入earlySingletonObjects,然后整個單例創(chuàng)建完成在塞入singletonObjects霉祸。存放在singletonFactories好處是可擴展筑累,我們在這個里面會調用beanPostProcessor 從而可以在我們實現提前獲取對象引用的時候進行一些操作