1.什麼是迴圈依賴? 迴圈依賴是指一個或多個對象之間存在直接或間接的依賴關係,這種依賴關係構成一個環形調用 , 舉個例子 : A 依賴B , B依賴C , C依賴A , 這樣就形成了迴圈依賴; 2.spring對迴圈依賴的處理有三種情況: ①構造器的迴圈依賴:這種依賴spring是處理不了的,直接拋 ...
1.什麼是迴圈依賴?
迴圈依賴是指一個或多個對象之間存在直接或間接的依賴關係,這種依賴關係構成一個環形調用 , 舉個例子 : A 依賴B , B依賴C , C依賴A , 這樣就形成了迴圈依賴;
2.spring對迴圈依賴的處理有三種情況:
①構造器的迴圈依賴:這種依賴spring是處理不了的,直接拋出BeanCurrentlyInCreationException異常。
②單例模式下的setter迴圈依賴:通過"三級緩存”處理迴圈依賴。
③非單例迴圈依賴:無法處理。
三級緩存的執行邏輯
- 先從“第一級緩存”找對象,有就返回,沒有就找“二級緩存”
- 找“二級緩存”,有就返回,沒有就找“三級緩存”
- 找“三級緩存”,找到了,就獲取對象,放到“二級緩存”,從“三級緩存”移除
3.下麵分析單例模式下的setter迴圈依賴如何解決
Spring的單例對象的初始化主要分為三步:
(1)createBeanInstance:實例化,其實也就是調用對象的構造方法實例化對象
(2)populateBean:填充屬性,這一步主要是多bean的依賴屬性進行填充
(3)initializeBean:調用spring xml中的init 方法.
從上面講述的單例bean初始化步驟我們可以知道,迴圈依賴主要發生在第一,第二部.也就是構造器循 環依賴和field迴圈依賴.
舉例:A的某個field或者setter依賴了B的實例對象,同時B的某個field或者setter依賴了A的實例對象”這種迴圈依賴的情況.
A首先完成了 初始化的第一步(createBeanINstance實例化),並且將自己提前曝光到singletonFactories中.
此時進行初始化的第二步,發現自己依賴對象B,此時就嘗試去get(B),發現B還沒有被create,所以走 create流程,B在初始化第一步的時候發現自己依賴了對象A,於是嘗試get(A),嘗試一級緩存 singletonObjects(肯定沒有,因為A還沒初始化完全),嘗試二級緩存earlySingletonObjects(也沒 有),嘗試三級緩存singletonFactories,由於A通過ObjectFactory將自己提前曝光了,所以B能夠通過 ObjectFactory.getObject拿到A對象(雖然A還沒有初始化完全,但是總比沒有好呀),B拿到A對象後順利 完成了初始化階段1,2,3,完全初始化之後將自己放入到一級緩存singletonObjects中.
此時返回A中,A此時能拿到B的對象順利完成自己的初始化階段2,3,最終A也完成了初始化,進去了 一級緩存singletonObjects中,而且更加幸運的是,由於B拿到了A的對象引用,所以B現在hold住的A對 象完成了初始化.