原來Spring是這樣解決迴圈依賴的

2021-10-23 10:23:04 字數 1795 閱讀 5929

什麼是迴圈依賴

通常來說,spring迴圈依賴的場景一般是單例bean。

@component

public class a

@component

public class b

@component

public class c

效果圖如下:

效果圖如下:

先說明前提:原型(prototype)的場景是不支援迴圈依賴的,通常會走到abstractbeanfactory類中下面的判斷,丟擲異常。

當建立a的時候,發現要注入原型欄位b,又建立新的b發現要注入原型欄位a,這個時候就會丟擲beancurrentlyincreationexception異常。

if (isprototypecurrentlyincreation(beanname))
舉個栗子

ioc 容器在讀到上面的配置時,會按照順序,先去例項化 beana。然後發現 beana 依賴於 beanb,接在又去例項化 beanb。例項化 beanb 時,發現 beanb 又依賴於 beana。如果容器不處理迴圈依賴的話,容器會無限執行上面的流程,直到記憶體溢位,程式崩潰。

當然,spring 是不會讓這種情況發生的。在容器再次發現 beanb 依賴於 beana 時,容器會獲取 beana 物件的乙個早期的引用(early reference),並把這個早期引用注入到 beanb 中,讓 beanb 先完成例項化。beanb 完成例項化,beana 就可以獲取到 beanb 的引用,beana 隨之完成例項化。

spring是如何解決迴圈依賴的

public class defaultsingletonbeanregistry extends ******aliasregistry implements singletonbeanregistry
首先spring維護了三個map,也就是我們通常說的**快取。

spring通過**快取解決了迴圈依賴,其中一級快取為單例池(singletonobjects),二級快取為早期**物件earlysingletonobjects,**快取為早期**物件工廠(singletonfactories)。

當a、b兩個類發生迴圈引用時,在a完成例項化後,就使用例項化後的物件去建立乙個物件工廠,並新增到**快取中,如果a被aop**,那麼通過這個工廠獲取到的就是a**後的物件,如果a沒有被aop**,那麼這個工廠獲取到的就是a例項化的物件。

當a進行屬性注入時,會去建立b,同時b又依賴了a,所以建立b的同時又會去呼叫getbean(a)來獲取需要的依賴,此時的getbean(a)會從快取中獲取,第一步,先獲取到**快取中的工廠;第二步,呼叫物件工工廠的getobject方法來獲取到對應的物件,得到這個物件後將其注入到b中。

緊接著b會走完它的生命週期流程,包括初始化、後置處理器等。當b建立完後,會將b再注入到a中,此時a再完成它的整個生命週期。至此,迴圈依賴結束!

簡單一句話說:先去快取裡找bean,沒有則例項化當前的bean放到map,如果有需要依賴當前bean的,就能從map取到

for迴圈原來是這樣

for迴圈可以說是程式中最靈活,最常用,最重要的乙個迴圈用法,大家經常用到,但是你真正理解for迴圈的執行原理嗎?舉個例子 for i 0 i 8 i 對於這個語句執行結束的時候 i 是多少?經常用,卻沒怎麼注意,執行結束的時候 i 是8 下面說一下for迴圈語句的執行過程 for 表示式1 表示式...

原來多型是這樣子的!

多型 什麼是多型 polymorphi 按字面的意思就是 多種形狀 引用charlie calverts對多型的描述 多 態性是允許你將父物件設定成為和乙個或更多的他的子物件相等的技術,賦值之後,父物件就可以根據當前 賦值給它的子物件的特性以不同的方式運作 摘自 delphi4 程式設計技術內幕 簡...

快速排序 原來是這樣

咚咚咚,開講啦!今天呢,讓我們來看看一種快速的排序方法,哈哈,它的名字就叫做快速排序,時間複雜度 o nlogn 首先呢,以第乙個數 為了方便 為基準數也可以叫參照數,隨你怎麼叫,就是拿來參照的。比如 這樣一組亂序的數字 i j 6 1 2 7 9 3 4 5 10 8 小i站在 6 上面,小j站在...