Spring 迴圈依賴問題

2021-10-02 16:34:18 字數 3544 閱讀 9593

"a" class

="com.demo.circularreference.a"

>

name

="b"

ref="b"

/>

bean

>

"b" class

="com.demo.circularreference.b"

>

name

="a"

ref="a"

/>

bean

>

public

classa}

public

class

b}

spring中將迴圈依賴的處理分為了3種情況

通過構造器注入形成的迴圈依賴是無法解決的,容器中會丟擲beancurrentlyincreationexception異常。

首先需要明確的一點是,容器會標識乙個當前正在建立的bean,將它記錄在快取singletonscurrentlyincreation中。

public

class

defaultsingletonbeanregistry

extends

******aliasregistry

implements

singletonbeanregistry

//將bean id加入singletonscurrentlyincreation,如果加入失敗則丟擲illegalstateexception

beforesingletoncreation

(beanname)

;//例項化單例bean

singletonobject = singletonfactory.

getobject()

;//將bean id從singletonscurrentlyincreation中移除,如果移除失敗則丟擲beancurrentlyincreationexception

aftersingletoncreation

(beanname)

; newsingleton =

true;if

(newsingleton)

}return singletonobject;

}}

構造器注入和setter注入的不同之處在於,構造器注入的方式在通過構造方法例項化bean的時候就直接尋找依賴注入了,而setter注入需要在例項化步驟中先通過預設的無參構造方法例項化bean以後,再在後續方法中通過setter方法尋找依賴注入。這就導致通過構造器注入例項化a的時候,會直接去尋找依賴b,而依賴b又會去尋找依賴a,此時a和b的id都已經存在於快取singletonscurrentlyincreation 中,當再次尋找a想加入快取的時候,就會新增失敗進而丟擲beancurrentlyincreationexception異常。

一般是指單例bean之間能構成迴圈依賴。承接上文來說,當單例a例項化完成後會快取在singletonfactories中。這樣在setter注入b的時候,b需要去獲取a,在dogetbean方法開頭通過getsingleton中就可以直接返回。

protected object docreatebean

(final string beanname,

final rootbeandefinition mbd,

final

@nullable object[

] args)

throws beancreationexception ()

; class<?(

);if(beantype != nullbean.

class

)//讓例項化後的bean早早暴露出來,方便setter注入時依賴bean能提前發現依賴

boolean earlysingletonexposure =

(mbd.

issingleton()

&&this

.allowcircularreferences &&

issingletoncurrentlyincreation

(beanname));

if(earlysingletonexposure)

//加入到快取singletonfactories中

addsingletonfactory

(beanname,()

->

getearlybeanreference

(beanname, mbd, bean));

} object exposedobject = bean;

//setter注入

populatebean

; exposedobject =

initializebean

(beanname, exposedobject, mbd)

;return exposedobject;

}

protected

t dogetbean

(final string name,

@nullable

final class

requiredtype,

@nullable

final object[

] args,

boolean typecheckonly)

throws bean***ception }}

}return singletonobject;

}

對於兩個原型bean是無法處理迴圈依賴的。在dogetbean方法中就存在校驗。

protected

t dogetbean

(final string name,

@nullable

final class

requiredtype,

@nullable

final object[

] args,

boolean typecheckonly)

throws bean***ception

else

實際原因也很簡單,原型bean不會被記錄在快取singletonfactory中。因為迴圈依賴中,當a去尋找b,b也會去尋找a,但是此時b找到的a不再是之前的a,而是乙個新的a (prototype),這就導致這樣的依賴關係沒有終點,造成了死迴圈。

但是在某些場景下單例bean和原型bean是能構成迴圈依賴的。

singleton beana和prototype beanb 兩者構成迴圈依賴,當執行getbean方法執行存在先後順序的時候,先通過getbean方法獲取a的時候是可行的,但是先通過getbean方法獲取b就不行了。因為先通過getbean方法獲取a的時候,先例項化了單例a,再注入原型b,原型b中可以找到單例a,就能構成一次有終點的迴圈依賴。反之,先通過getbean方法獲取b的時候,先例項化原型b,再注入單例a,單例a又依賴於乙個新的原型b,這樣就無法構成迴圈依賴了。因此在這個場景下,執行例項化的順序十分重要。

spring迴圈依賴問題

在開始介紹各種情況之前,首先要了解以下三個知識點 spring中依賴注入的方式有兩種,屬性注入與構造器注入。上面的 中,類a就是通過屬性注入的方式注入了b,類b是通過構造器注入的方式注入了a。spring中的bean根據作用域的不同,可以大體分為兩類,singleton和prototype。sing...

Spring迴圈依賴問題(筆記)

a類中有成員變數b類的物件。b類中也有成員變數a類的物件。簡單來說就,就是如下情況 class a class b 在一開始的開始 也就是程式第一次獲取a的例項時,需要從spring容器單例池中獲取。但此時單例池中還沒有a的例項,所以要new 乙個a物件。在a例項 建立和初始化的時候,要獲取成員變數...

spring 迴圈依賴

構造器依賴無法解決,使用 快取解決field屬性依賴。a的屬性依賴b,b的屬性依賴a 建立a,設定依賴屬性b,發現b沒有建立,建立b,設定依賴屬性a,先從一級快取singletonobjects中去獲取。如果獲取到就直接return 如果獲取不到或者物件正在建立中 issingletoncurren...