spring學習筆記 七 迴圈依賴解決思路

2021-10-02 08:45:27 字數 2009 閱讀 2041

這章我們主要來聊聊在docreatebean()方法中,`spring是如何解決迴圈依賴的,以及一些錯誤的使用方式。

假設現在我們有兩個類,分別是a類,b類,同時a類需要引用b類,b類需要引用a類,也就是套娃模式。

@component

public

class

a@component

public

class

b

那麼spring如何處理這種情況呢?

在這裡我們重新回顧一下spring對於bean載入的流程。

其實前面的載入流程出來了解決方案就很簡單了,只要在填充bean屬性之間將直接放到beanfactory中就可以了,這樣後面依賴到當前bean就可以直接從beanfactory中取出,然後返回出去了,不用在走建立bean流程。

下面我們以bean的視角來看下是如何解決的。

這樣就跳出了一直建立的死迴圈。

看了上面的解決方案是否覺得就安全了呢?就可以放心大膽的迴圈依賴bean了?

下面我們在來看乙個例子,還是基於上面的兩個類,只做一些小小的改變。

@component

public

classa}

@component

public

class

b}

我們只是在乙個方法上新增了乙個註解@async,然後情況就會出現翻天覆地的變化。

不是說的好好的,已經解決了迴圈依賴問題嘛?怎麼又報出這個錯誤?

這個@async註解到底是什麼妖魔鬼怪。

我們首先來看看,這個錯誤到底是哪個地方丟擲來的。

下面這段**發生在bean建立完畢之後。

if

(earlysingletonexposure)

elseif(

!this

hasdependentbean

(beanname))}

if(!actualdependentbeans.

isempty()

)}}}

還是分步走

第一步,通過beanfactory獲取到原始bean

第二步,判斷建立的bean與獲取的bean是否相同(重要…有些同學靈光乍現了嗎?),相同則直接返回建立的bean

如果是一般情況,我們在第二步就會直接返回,因為我們建立的bean和原始的bean是一模一樣的。(也就是沒有@async註解的時候,靈光乍現了嘛?)

那麼反過來一想,使用@async註解就會導致我們建立的bean和從beanfactory中獲取到的原始bean不一致。

為什麼呢?

首先@async註解的作用就是將同步操作轉換成非同步操作,那麼如何無侵入的實現呢? **對吧。 so,建立的bean返回的就是**類。 所以不一樣。

所以只要註解會導致bean被**,就會導致這個問題。(迴圈依賴)

所以怎麼解決呢?

@lazy註解,由於spring的@lazy會讓判斷條件無法達成而跳過檢測。

elseif(

!this

hasdependentbean

(beanname)

)

因為@lazy註解也是返回的**bean,所以spring讓這個bean跳過了本次檢測。

例項:

@component

public

classa}

@component

public

class

b}

Spring學習 迴圈依賴

來自 由springioc去建立bean物件,主要有兩個問題,乙個死迴圈的建立,乙個是aop的 建立過程 先去獲取a,但a例項化的時候,就會把a放到半成品池中去,然後去填充屬性b,然後獲取b,b在單例池中判斷是否有a,如果沒有就去半成品池中去獲取,如果半成品中有把a放到b中就進行填充和初始化,然後b...

Spring解決迴圈依賴 筆記

參考 spring內部維護了三個map,也就是我們通常說的 快取,位置在defaultsingletonbeanregistry private final mapsingletonobjects new concurrenthashmap 256 private final map singlet...

Spring迴圈依賴問題(筆記)

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