回覆列表
  • 1 # 星夜無雙

    一、迴圈依賴的產生和解決的前提迴圈依賴的產生可能有很多種情況,例如:

    A的構造方法中依賴了B的例項物件,同時B的構造方法中依賴了A的例項物件A的構造方法中依賴了B的例項物件,同時B的某個field或者setter需要A的例項物件,以及反之A的某個field或者setter依賴了B的例項物件,同時B的某個field或者setter依賴了A的例項物件,以及反之Spring對於迴圈依賴的解決不是無條件的,首先前提條件是針對scope單例並且沒有顯式指明不需要解決迴圈依賴的物件,而且要求該物件沒有被代理過。同時Spring解決迴圈依賴也不是萬能,以上三種情況只能解決兩種,第一種在構造方法中相互依賴的情況Spring也無力迴天。

    二、Spring迴圈依賴的理論依據Spring迴圈依賴的理論依據其實是Java基於引用傳遞,當我們獲取到物件的引用時,物件的field或者或屬性是可以延後設定的。Spring單例物件的初始化其實可以分為三步:(例項化、填充屬性、初始化)

    createBeanInstance, 例項化,實際上就是呼叫對應的構造方法構造物件,此時只是呼叫了構造方法,spring xml中指定的property並沒有進populate:populateBean,填充屬性,這步對spring xml中指定的property進行populateinitializeBean,呼叫spring xml中指定的init方法,或者AfterPropertiesSet方法會發生迴圈依賴的步驟集中在第一步和第二步。三、三級快取對於單例物件來說,在Spring的整個容器的生命週期內,有且只存在一個物件,很容易想到這個物件應該存在Cache中,Spring大量運用了Cache的手段,在迴圈依賴問題的解決過程中甚至使用了“三級快取”。“三級快取”主要是指

    從字面意思來說:singletonObjects指單例物件的cache,singletonFactories指單例物件工廠的cache,earlySingletonObjects指提前曝光的單例物件的cache。以上三個cache構成了三級快取,Spring就用這三級快取巧妙的解決了迴圈依賴問題。三級快取的用法:

    首先解釋兩個引數:

    isSingletonCurrentlyInCreation 判斷對應的單例物件是否在建立中,當單例物件沒有被初始化完全(例如A定義的建構函式依賴了B物件,得先去建立B物件,或者在populatebean過程中依賴了B物件,得先去建立B物件,此時A處於建立中)allowEarlyReference 是否允許從singletonFactories中透過getObject拿到物件分析getSingleton的整個過程,Spring首先從singletonObjects(一級快取)中嘗試獲取,如果獲取不到並且物件在建立中,則嘗試從earlySingletonObjects(二級快取)中獲取,如果還是獲取不到並且允許從singletonFactories透過getObject獲取,則透過singletonFactory.getObject()(三級快取)獲取。如果獲取到了則將singletonObject放入到earlySingletonObjects,也就是 將三級快取提升到二級快取中!

    Spring解決迴圈依賴的訣竅就在於singletonFactories這個cache,這個cache中存的是型別為ObjectFactory,其定義如下:

    在bean建立過程中,有兩處比較重要的匿名內部類實現了該介面。一處是Spring利用其建立bean的時候,另一處就是:

    此處就是解決迴圈依賴的關鍵,這段程式碼發生在createBeanInstance之後,也就是說單例物件此時已經被創建出來的。這個物件已經被生產出來了,雖然還不完美(還沒有進行初始化的第二步和第三步),但是已經能被人認出來了(根據物件引用能定位到堆中的物件),所以Spring此時將這個物件提前曝光出來讓大家認識,讓大家使用。這樣做有什麼好處呢?讓我們來分析一下“A的某個field或者setter依賴了B的例項物件,同時B的某個field或者setter依賴了A的例項物件”這種迴圈依賴的情況。A首先完成了初始化的第一步,並且將自己提前曝光到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物件也蛻變完美了!一切都是這麼神奇!!

    二級快取有啥用??

    其實按道理是可以二級快取就可以初始化一些內容,但是在這裡

    在將三級快取放入二級快取的時候,會判斷是否有SmartInstantiationAwareBeanPostProcessor這樣的後置處理器,換句話說這裡是給使用者提供介面擴充套件的,所以採用了三級快取。

  • 2 # 星夜無雙

    一、迴圈依賴的產生和解決的前提迴圈依賴的產生可能有很多種情況,例如:

    A的構造方法中依賴了B的例項物件,同時B的構造方法中依賴了A的例項物件A的構造方法中依賴了B的例項物件,同時B的某個field或者setter需要A的例項物件,以及反之A的某個field或者setter依賴了B的例項物件,同時B的某個field或者setter依賴了A的例項物件,以及反之Spring對於迴圈依賴的解決不是無條件的,首先前提條件是針對scope單例並且沒有顯式指明不需要解決迴圈依賴的物件,而且要求該物件沒有被代理過。同時Spring解決迴圈依賴也不是萬能,以上三種情況只能解決兩種,第一種在構造方法中相互依賴的情況Spring也無力迴天。

    二、Spring迴圈依賴的理論依據Spring迴圈依賴的理論依據其實是Java基於引用傳遞,當我們獲取到物件的引用時,物件的field或者或屬性是可以延後設定的。Spring單例物件的初始化其實可以分為三步:(例項化、填充屬性、初始化)

    createBeanInstance, 例項化,實際上就是呼叫對應的構造方法構造物件,此時只是呼叫了構造方法,spring xml中指定的property並沒有進populate:populateBean,填充屬性,這步對spring xml中指定的property進行populateinitializeBean,呼叫spring xml中指定的init方法,或者AfterPropertiesSet方法會發生迴圈依賴的步驟集中在第一步和第二步。三、三級快取對於單例物件來說,在Spring的整個容器的生命週期內,有且只存在一個物件,很容易想到這個物件應該存在Cache中,Spring大量運用了Cache的手段,在迴圈依賴問題的解決過程中甚至使用了“三級快取”。“三級快取”主要是指

    從字面意思來說:singletonObjects指單例物件的cache,singletonFactories指單例物件工廠的cache,earlySingletonObjects指提前曝光的單例物件的cache。以上三個cache構成了三級快取,Spring就用這三級快取巧妙的解決了迴圈依賴問題。三級快取的用法:

    首先解釋兩個引數:

    isSingletonCurrentlyInCreation 判斷對應的單例物件是否在建立中,當單例物件沒有被初始化完全(例如A定義的建構函式依賴了B物件,得先去建立B物件,或者在populatebean過程中依賴了B物件,得先去建立B物件,此時A處於建立中)allowEarlyReference 是否允許從singletonFactories中透過getObject拿到物件分析getSingleton的整個過程,Spring首先從singletonObjects(一級快取)中嘗試獲取,如果獲取不到並且物件在建立中,則嘗試從earlySingletonObjects(二級快取)中獲取,如果還是獲取不到並且允許從singletonFactories透過getObject獲取,則透過singletonFactory.getObject()(三級快取)獲取。如果獲取到了則將singletonObject放入到earlySingletonObjects,也就是 將三級快取提升到二級快取中!

    Spring解決迴圈依賴的訣竅就在於singletonFactories這個cache,這個cache中存的是型別為ObjectFactory,其定義如下:

    在bean建立過程中,有兩處比較重要的匿名內部類實現了該介面。一處是Spring利用其建立bean的時候,另一處就是:

    此處就是解決迴圈依賴的關鍵,這段程式碼發生在createBeanInstance之後,也就是說單例物件此時已經被創建出來的。這個物件已經被生產出來了,雖然還不完美(還沒有進行初始化的第二步和第三步),但是已經能被人認出來了(根據物件引用能定位到堆中的物件),所以Spring此時將這個物件提前曝光出來讓大家認識,讓大家使用。這樣做有什麼好處呢?讓我們來分析一下“A的某個field或者setter依賴了B的例項物件,同時B的某個field或者setter依賴了A的例項物件”這種迴圈依賴的情況。A首先完成了初始化的第一步,並且將自己提前曝光到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物件也蛻變完美了!一切都是這麼神奇!!

    二級快取有啥用??

    其實按道理是可以二級快取就可以初始化一些內容,但是在這裡

    在將三級快取放入二級快取的時候,會判斷是否有SmartInstantiationAwareBeanPostProcessor這樣的後置處理器,換句話說這裡是給使用者提供介面擴充套件的,所以採用了三級快取。

  • 中秋節和大豐收的關聯?
  • 今年的詹姆斯,奪冠希望真的渺茫嗎?