這章我們主要來聊聊在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例項 建立和初始化的時候,要獲取成員變數...