例項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不會進行加鎖...