如果 class a 中依賴了 class b並且class b 中也依賴了class a,形成乙個閉環就會產生迴圈依賴的問題。
構造器注入方式的迴圈依賴,無法解決;
setter注入方式的迴圈依賴,解決方式:
spring先用構造器例項化bean物件,將例項化結束的物件放到乙個map中,並且spring提供獲取這個未設定屬性的例項化物件的引用方法;
在進行屬性注入的時候,依次獲取到對應的bean例項物件進行注入;
在 abstractbeanfactory 的 dogetbean 方法中,會首先通過快取中去查詢單例 bean 物件。呼叫 getsingleton 方法,原始碼如下:
protected object getsingleton
(string beanname,
boolean allowearlyreference)}}
}return singletonobject;
}
從這個方法上我們可以看到 spring 使用**快取解決迴圈依賴問題,每個快取儲存例項物件引用的不同生命週期:
呼叫 createbeaninstance 方法進行例項化物件
呼叫 populatebean 方法進行依賴注入
呼叫 initializebean 方法執行 beanpostprocessor 後置處理器
我們來看看例項化完之後在什麼時候儲存到 singletonfactories 快取中,在 abstractautowirecapablebeanfactory.docreatebean() 方法中。
protected object docreatebean
(final string beanname,
final rootbeandefinition mbd,
final
@nullable object[
] args)
throws beancreationexception
if//...
// 向容器中快取單例模式的bean物件,以防止迴圈引用
boolean earlysingletonexposure =
(mbd.
issingleton()
&&this
.allowcircularreferences &&
issingletoncurrentlyincreation
(beanname));
if(earlysingletonexposure)
//為避免後期迴圈依賴,盡早持有物件的引用
addsingletonfactory
(beanname,()
->
getearlybeanreference
(beanname, mbd, bean));
}//...
}protected
void
addsingletonfactory
(string beanname, objectfactory<
?> singletonfactory)
}}
可以看到在 createbeaninstance 方法例項化物件之後(此時還未進行依賴注入)就會暴露到 singletonfactories **快取集合中,以解決屬性注入的迴圈引用問題。
在 abstractbeanfactory 的 dogetbean 方法中,呼叫 createbean 方法
//建立單例模式的bean的例項物件
if(mbd.
issingleton()
)catch
(bean***ception ex)})
;//獲取給定bean的例項物件,主要完成factorybean獲取例項化物件過程
bean =
getobjectforbeaninstance
(sharedinstance, name, beanname, mbd)
;}
繼續跟進 defaultsingletonbeanregistry.getsingleton() 方法,原始碼如下:
public object getsingleton
(string beanname, objectfactory<
?> singletonfactory)
if(logger.
isdebugenabled()
)beforesingletoncreation
(beanname)
;boolean newsingleton =
false
;boolean recordsuppressedexceptions =
(this
.suppressedexceptions == null);if
(recordsuppressedexceptions)
trycatch
(illegalstateexception ex)
}catch
(beancreationexception ex)
}throw ex;
}finally
aftersingletoncreation
(beanname);}
if(newsingleton)
}return singletonobject;}}
protected
void
addsingleton
(string beanname, object singletonobject)
}
從上面可看到,當 bean 例項初始化完成後將會刪除 singletonfactories 和 earlysingletonobjects 快取中的引用,新增到 singletonobjects 快取中。
最後梳理一下spring解決迴圈依賴的流程
1. 類 a 與 b 中屬性相互引用,造成迴圈依賴
2. a 例項化完成,將自己提前**到 singletonfactories 快取中
3. a 例項進行依賴注入,發現自己依賴物件 b,就嘗試獲取 b 例項引用
4. b 此時還沒初始化,先進行例項化並將自己**到 singletonfactories 快取中
5. b 例項進行依賴注入,發現自己依賴物件 a,就嘗試獲取 a 例項引用
6. 由於 a 例項尚未初始化完成,從 singletonobjects 中獲取不到,從 earlysingletonobjects 中獲取也沒有,最後從 singletonfactories 中獲取到
7. a 例項從 singletonfactories 中刪除,新增到 earlysingletonobjects 快取中去
8. b 例項拿到 a 例項引用後順利完成依賴注入及初始化,並將自己從 singletonfactories 快取中刪除,新增到 singletonobjects 快取中
9. a 例項獲取 b 例項引用後,a 例項也能繼續完成依賴注入及後續初始化操作
10. a 是從 earlysingletonobjects 中刪除,新增到 singletonobjects 快取中
在整個過程中,a 和 b 的例項引用並未改變過。只是在 bean 生命週期的不同階段。 Spring學習之迴圈依賴
很簡單,就是a物件依賴了b物件,b物件依賴了a物件。例如 a依賴了b class a b依賴了a class b那麼迴圈依賴是個問題嗎?如果不考慮spring,迴圈依賴並不是問題,因為物件之間相互依賴是很正常的事情。例如 a a newa b b newb a.b b b.a a 這樣,a,b就依賴...
spring 迴圈依賴
構造器依賴無法解決,使用 快取解決field屬性依賴。a的屬性依賴b,b的屬性依賴a 建立a,設定依賴屬性b,發現b沒有建立,建立b,設定依賴屬性a,先從一級快取singletonobjects中去獲取。如果獲取到就直接return 如果獲取不到或者物件正在建立中 issingletoncurren...
spring迴圈依賴
關於spring迴圈依賴網上有太多的例子,本文只是簡單的記錄一下。本文預設讀者熟悉spring核心之一控制反轉和依賴注入 在我們的開發過程中,我們基本上對迴圈依賴是無感且不用去考慮如何解決。如上圖中classa使用屬性注入了classb,classb使用屬性注入了classa。如上圖這就是產生了迴圈...