Spring如何解決迴圈依賴

2021-10-19 08:12:42 字數 1414 閱讀 9261

比如:在a類引入b物件,在b類引入a物件,建立a的時候需要依賴b,建立b的時候需要依賴a,而各自建立物件的時候,其互相依賴的物件還沒有建立完成,就導致各自都無法成功建立物件。這就是迴圈依賴。

class

aclass

b

解決迴圈依賴的方法很簡單,如下所示,先例項化a和b,此時都沒初始化,即都沒有對各自物件裡面的屬性進行賦值,接下來可以通過set方法,把例項a和例項b set到各自的物件屬性中去,這樣一來就解決迴圈依賴問題。

a a =

newa()

;b b =

newb()

;a.setb

(b);

b.seta

(a);

但是,如果a和b類都使用含參構造器的方法進行例項化,就沒法解決迴圈依賴問題了,因為在使用含參構造器的方法,需要將屬性值先例項化出來,a依賴屬性b,就需要先將b例項化,可以此時b的例項化也依賴a,這樣就沒法例項化了。

a a =

newa

(b);

b b =

newb

(a);

所以,解決迴圈依賴問題的主要思想是:先例項化每個類,再把例項set到依賴它的例項中去,即先例項化,再初始化

既然普通的建立物件方法可以用上文描述的方法來解決,那麼spring怎麼解決迴圈依賴的問題?

首先spring有兩大特性ioc和aop:

我們再來看看spring解決迴圈依賴的基本思想:先new,後set,即和上文描述的一樣,也是先例項化,再初始化的方式。

那麼spring如何具體實現的呢?**快取

在spring中,設定了三個快取物件來快取bean:

一級快取存入的是初始化後的bean,是供呼叫者直接拿來用的,如果只使用一級快取,那麼未初始化的bean就會放進去,那麼如果這個bean的內部依賴被呼叫的話,就會造成空指標異常,因為這個bean還沒有初始化,其依賴還沒有注入,所以單單使用一級快取是不可以的。

一級快取是存放初始化後的bean,單單使用一級快取行不通,那麼我們就再加一層快取,二級快取是存放例項化而未初始化的bean的,那麼使用二級快取可以嗎?

首先,假設要例項化a,看下面的**

class

aclass

b

例項化流程如下:

我們發現二級快取可以解決迴圈依賴的問題,那麼為什麼需要**快取呢?

首先,我們看看spring載入bean的過程:

問題出在aop這裡,如果沒有aop,使用二級快取是可以解決迴圈依賴問題的,因為aop後,是需要生成**物件的。假設這個a類被aop了,我們還是使用二級快取的話,過程如下:

spring如何解決迴圈依賴

1.構造器注入 無法解決 構造器注入時,a,b都沒有進行初始化物件 構造方法無法執行完成 2.spring 為了解決單例的迴圈依賴問題,使用了 快取。其中一級快取為單例池 singletonobjects 二級快取為提前 物件 earlysingletonobjects 快取為提前 物件工廠 sin...

Spring如何解決迴圈依賴

多個bean之間相互依賴,形成了乙個閉環。比如 a依賴於b b依賴於c c依賴於a 通常來說,如果問spring容器內部如何解決迴圈依賴,一定是指預設的單例bean中,屬性互相引用的場景。也就是說,spring的迴圈依賴,是spring容器注入時候出現的問題。例項化a 將半成品的a放入singlet...

Spring如何解決迴圈依賴的?

假設有兩個例項a,b迴圈依賴。且作用域都是單例,因為spring只支援單例的迴圈依賴。假設掃瞄到了a,呼叫getbean方法,由於是單例,呼叫getsingleton方法,發現三個緩中都沒有a,進入createbeaninstance的流程。此時建立的是能夠建立a的工廠放進了 快取裡面,然後執行po...