spring迴圈依賴深入理解

2021-09-24 11:40:26 字數 2978 閱讀 8190

例項a->例項b->例項c->例項a。例項間的依賴構成閉環。spring 預設是支援迴圈依賴的(setter).

public abstractautowirecapablebeanfactory()
迴圈依賴分為三種:

構造器迴圈依賴

setter迴圈依賴

多例迴圈依賴 

其中第一種和第三種是直接報錯的,spring 無法解決。所以我們說的主要是setter迴圈依賴。

spring 利用 單例bean初始化過程的多階段性,提前暴露了某個階段的單例bean,從而解決了迴圈依賴。

下圖比較簡單地說明了一下:

我們直接看建立bean的原始碼來分析

abstractautowirecapablebeanfactory:278
protected object docreatebean(final string beanname, final rootbeandefinition mbd, object args) throws beancreationexception 

}//初始化第一步 獲取到乙個簡單的物件,還沒屬性賦值

// 。。。。省略的**

//判斷是否提前暴漏自己: 單例 && 允許迴圈依賴 && 還在初始化階段

boolean earlysingletonexposure = mbd.issingleton() && this.allowcircularreferences && this.issingletoncurrentlyincreation(beanname);

if (earlysingletonexposure)

//重要 重要 就是這裡把自己的乙個factorybean提前暴漏了,放進singletonfactories(map)中

this.addsingletonfactory(beanname, new objectfactory()

});}

//返回值

object exposedobject = bean;

try

} catch (throwable var18)

throw new beancreationexception(mbd.getresourcedescription(), beanname, "initialization of bean failed", var18);

}// 。。。省略**

try catch (beandefinitionvalidationexception var16)

}

好了這是建立bean的乙個大體的過程。在建立a bean的時候,把乙個factorybean給提前暴露了。然後再注入b bean例項的時候,還是繼續建立b bean的過程,(注意此時a的乙個factorybean已經暴漏了)但是在給b bean設定依賴的時候,獲取a bean 的方法裡會獲取到乙個a 的乙個factorybean.從而完成b的初始化。

所以第二個重點的過程就是獲取bean的方法,做了什麼手腳,讓b獲取到了乙個提前暴露的a bean

abstractbeanfactory:108
public object getbean(string name) throws bean***ception 

protected t dogetbean(string name, classrequiredtype, final object args, boolean typecheckonly) throws bean***ception else

//檢查是否與要求的型別匹配 跟主題無關,可跳過

if (requiredtype != null && bean != null && !requiredtype.isassignablefrom(bean.getclass())) catch (typemismatchexception var22)

throw new beannotofrequiredtypeexception(name, requiredtype, bean.getclass());

}} else

}

接下來我們繼續看重要的乙個方法getsingleton(beanname)

public object getsingleton(string beanname) 

protected object getsingleton(string beanname, boolean allowearlyreference) }}

}return singletonobject != null_object ? singletonobject : null;

}

到這裡相信大家應該有一定的理解了吧。

接下來重點說下上面出現的幾個重要的map

private final mapsingletonobjects = new concurrenthashmap(256);

private final map> singletonfactories = new hashmap(16);

private final mapearlysingletonobjects = new hashmap(16);

也可以說是單例bean例項化過程的**快取機制。

建立開始 把自己的乙個factorybean放進singletonfactories(第**快取)中

在建立過程中其他類如果需要自己的時候,通過singletonfactories獲取到factorybean,然後獲取到例項返回,同時從第**快取中移除,放進第二級快取earlysingletonobjects

初始化完成後,把例項放進一級快取 singletonobjects,同時從**快取和二級快取中移除掉

深入理解Spring4框架(四) 依賴

乙個典型的企業應用不止包含乙個物件,即使是乙個簡單的應用,也是由幾個物件合作來完成使用者需要使用的功能。本節將介紹定義的bean是如何在真實系統中配合來完成既定功能的。依賴注入就是在物件構建完成後,為其定義依賴的過程。容器會在建立bean的時候將這些依賴注入進去。這個過程跟我們通常編碼不同,平常我們...

深入理解Spring框架中的 依賴注入

spring framework spring框架的核心概念就是 依賴注入 什麼是依賴注入?其實理解起來很簡單,依賴注入其實就是框架用於連線各個應用程式的一項技術。框架負責將你的應用程式中的各種相互依賴進行連線起來,並從應用程式 中完全解決掉連線邏輯和物件建立。舉乙個描述收銀機的例子 1.建立乙個介...

深入理解spring事務

事務介紹 乙個事務要麼同時成功,要麼同時失敗 特性事務隔離級別 傳播行為 唯讀事務只進行讀取操作 readonly true 告訴spring當前事務只會進行讀取操作,不會進行修改操作,可以幫助資料庫引擎優化 注 如果設定為唯讀的話,千萬不要在事務裡修改資料,使用唯讀操作時,spring不會進行加鎖...