1.什么是循環(huán)依賴?
循環(huán)依賴是指一個(gè)或多個(gè)對象之間存在直接或間接的依賴關(guān)系,這種依賴關(guān)系構(gòu)成一個(gè)環(huán)形調(diào)用 , 舉個(gè)例子 : A 依賴B , B依賴C , C依賴A , 這樣就形成了循環(huán)依賴;
?
2.spring對循環(huán)依賴的處理有三種情況:
①構(gòu)造器的循環(huán)依賴:這種依賴spring是處理不了的,直接拋出BeanCurrentlyInCreationException異常。
②單例模式下的setter循環(huán)依賴:通過"三級(jí)緩存”處理循環(huán)依賴。
③非單例循環(huán)依賴:無法處理。
三級(jí)緩存的執(zhí)行邏輯
- 先從“第一級(jí)緩存”找對象,有就返回,沒有就找“二級(jí)緩存”
- 找“二級(jí)緩存”,有就返回,沒有就找“三級(jí)緩存”
- 找“三級(jí)緩存”,找到了,就獲取對象,放到“二級(jí)緩存”,從“三級(jí)緩存”移除
3.下面分析單例模式下的setter循環(huán)依賴如何解決
Spring的單例對象的初始化主要分為三步:
(1)createBeanInstance:實(shí)例化,其實(shí)也就是調(diào)用對象的構(gòu)造方法實(shí)例化對象
(2)populateBean:填充屬性,這一步主要是多bean的依賴屬性進(jìn)行填充
(3)initializeBean:調(diào)用spring xml中的init 方法.
從上面講述的單例bean初始化步驟我們可以知道,循環(huán)依賴主要發(fā)生在第一,第二部.也就是構(gòu)造器循 環(huán)依賴和field循環(huán)依賴.
?舉例:A的某個(gè)field或者setter依賴了B的實(shí)例對象,同時(shí)B的某個(gè)field或者setter依賴了A的實(shí)例對象”這種循環(huán)依賴的情況.
A首先完成了 初始化的第一步(createBeanINstance實(shí)例化),并且將自己提前曝光到singletonFactories中.
此時(shí)進(jìn)行初始化的第二步,發(fā)現(xiàn)自己依賴對象B,此時(shí)就嘗試去get(B),發(fā)現(xiàn)B還沒有被create,所以走 create流程,B在初始化第一步的時(shí)候發(fā)現(xiàn)自己依賴了對象A,于是嘗試get(A),嘗試一級(jí)緩存 singletonObjects(肯定沒有,因?yàn)锳還沒初始化完全),嘗試二級(jí)緩存earlySingletonObjects(也沒 有),嘗試三級(jí)緩存singletonFactories,由于A通過ObjectFactory將自己提前曝光了,所以B能夠通過 ObjectFactory.getObject拿到A對象(雖然A還沒有初始化完全,但是總比沒有好呀),B拿到A對象后順利 完成了初始化階段1,2,3,完全初始化之后將自己放入到一級(jí)緩存singletonObjects中. 文章來源:http://www.zghlxwxcb.cn/news/detail-712301.html
此時(shí)返回A中,A此時(shí)能拿到B的對象順利完成自己的初始化階段2,3,最終A也完成了初始化,進(jìn)去了 一級(jí)緩存singletonObjects中,而且更加幸運(yùn)的是,由于B拿到了A的對象引用,所以B現(xiàn)在hold住的A對 象完成了初始化.文章來源地址http://www.zghlxwxcb.cn/news/detail-712301.html
到了這里,關(guān)于Spring怎么解決循環(huán)依賴問題?的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!