国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring 能解決所有循環(huán)依賴嗎?

這篇具有很好參考價值的文章主要介紹了Spring 能解決所有循環(huán)依賴嗎?。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

以下內(nèi)容基于 Spring6.0.4。

看了上篇文章的小伙伴,對于 Spring 解決循環(huán)依賴的思路應(yīng)該有一個大致了解了,今天我們再來看一看,按照上篇文章介紹的思路,有哪些循環(huán)依賴 Spring 處理不了。

嚴格來說,其實也不是解決不了,所有問題都有辦法解決,只是還需要額外配置,這個不是本文的主題,松哥后面再整文章和小伙伴們細聊。

1. 基于構(gòu)造器注入

如果依賴的對象是基于構(gòu)造器注入的,那么執(zhí)行的時候就會報錯,代碼如下:

@Service
public class AService {
    BService bService;

    public AService(BService bService) {
        this.bService = bService;
    }
}
@Service
public class BService {
    AService aService;

    public BService(AService aService) {
        this.aService = aService;
    }
}

運行時報錯如下:

Spring 能解決所有循環(huán)依賴嗎?,spring,java,后端

原因分析:

上篇文章我們說解決循環(huán)依賴的思路是加入緩存,如下圖:

Spring 能解決所有循環(huán)依賴嗎?,spring,java,后端

我們說先把 AService 原始對象創(chuàng)建出來,存入到緩存池中,然后再處理 AService 中需要注入的外部 Bean 等等,但是,如果 AService 依賴的 BService 是通過構(gòu)造器注入的,那就會導(dǎo)致在創(chuàng)建 AService 原始對象的時候就需要用到 BService,去創(chuàng)建 BService 時候又需要 AService,這樣就陷入到死循環(huán)了,對于這樣的循環(huán)依賴執(zhí)行時候就會出錯。

更進一步,如果我們在 AService 中是通過 @Autowired 來注入 BService 的,那么應(yīng)該是可以運行的,代碼如下:

@Service
public class AService {
    @Autowired
    BService bService;
}
@Service
public class BService {
    AService aService;

    public BService(AService aService) {
        this.aService = aService;
    }
}

上面這段代碼,AService 的原始對象就可以順利創(chuàng)建出來放到緩存池中,BService 創(chuàng)建所需的 AService 也就能從緩存中獲取到,所以就可以執(zhí)行了。

2. prototype 對象

循環(huán)依賴雙方 scope 都是 prototype 的話,也會循環(huán)依賴失敗,代碼如下:

@Service
@Scope("prototype")
public class AService {
    @Autowired
    BService bService;
}
@Service
@Scope("prototype")
public class BService {
    @Autowired
    AService aService;
}

這種循環(huán)依賴運行時也會報錯,報錯信息如下(跟前面報錯信息一樣):

Spring 能解決所有循環(huán)依賴嗎?,spring,java,后端

原因分析:

scope 為 prototype 意思就是說這個 Bean 每次需要的時候都現(xiàn)場創(chuàng)建,不用緩存里的。那么 AService 需要 BService,所以就去現(xiàn)場創(chuàng)建 BService,結(jié)果 BService 又需要 AService,繼續(xù)現(xiàn)場創(chuàng)建,AService 又需要 BService…,所以最終就陷入到死循環(huán)了。

3. @Async

帶有 @Async 注解的 Bean 產(chǎn)生循環(huán)依賴,代碼如下:

@Service
public class AService {
    @Autowired
    BService bService;

    @Async
    public void hello() {

    }
}
@Service
public class BService {
    @Autowired
    AService aService;

}

報錯信息如下:

Spring 能解決所有循環(huán)依賴嗎?,spring,java,后端

其實大家從這段報錯信息中也能看出來個七七八八:在 BService 中注入了 AService 的原始對象,但是 AService 在后續(xù)的處理流程中被 AOP 代理了,產(chǎn)生了新的對象,導(dǎo)致 BService 中的 AService 并不是最終的 AService,所以就出錯了!

那有小伙伴要問了,上篇文章我們不是說了三級緩存就是為了解決 AOP 問題嗎,為什么這里發(fā)生了 AOP 卻無法解決?

如下兩個前置知識大家先理解一下:

第一:

其實大部分的 AOP 循環(huán)依賴是沒有問題的,這個 @Async 只是一個特例,特別在哪里呢?一般的 AOP 都是由 AbstractAutoProxyCreator 這個后置處理器來處理的,通過這個后置處理器生成代理對象,AbstractAutoProxyCreator 后置處理器是 SmartInstantiationAwareBeanPostProcessor 接口的子類,并且 AbstractAutoProxyCreator 后置處理器重寫了 SmartInstantiationAwareBeanPostProcessor 接口的 getEarlyBeanReference 方法;而 @Async 是由 AsyncAnnotationBeanPostProcessor 來生成代理對象的,AsyncAnnotationBeanPostProcessor 也是 SmartInstantiationAwareBeanPostProcessor 的子類,但是卻沒有重寫 getEarlyBeanReference 方法,默認情況下,getEarlyBeanReference 方法就是將傳進來的 Bean 原封不動的返回去。

第二:

在 Bean 初始化的時候,Bean 創(chuàng)建完成后,后面會執(zhí)行兩個方法:

  • populateBean:這個方法是用來做屬性填充的。
  • initializeBean:這個方法是用來初始化 Bean 的實例,執(zhí)行工廠回調(diào)、init 方法以及各種 BeanPostProcessor。

大家先把這兩點搞清楚,然后我來跟大家說上面代碼的執(zhí)行流程。

  1. 首先 AService 初始化,初始化完成之后,存入到三級緩存中。
  2. 執(zhí)行 populateBean 方法進行 AService 的屬性填充,填充時發(fā)現(xiàn)需要用到 BService,于是就去初始化 BService。
  3. 初始化 BService 發(fā)現(xiàn)需要用到 AService,于是就去緩存池中找,找到之后拿來用,但是!?。∵@里找到的 AService 不是代理對象,而是原始對象。因為在三級緩存中保存的 AService 的那個 ObjectFactory 工廠,在對 AService 進行提前 AOP 的時候,執(zhí)行的是 SmartInstantiationAwareBeanPostProcessor 類型的后置處理器 中的 getEarlyBeanReference 方法,如果是普通的 AOP,調(diào)用 getEarlyBeanReference 方法最終會觸發(fā)提前 AOP,但是,這里執(zhí)行的是 AsyncAnnotationBeanPostProcessor 中的 getEarlyBeanReference 方法,該方法只是返回了原始的 Bean,并未做任何額外處理。
  4. 當 BService 創(chuàng)建完成后,AService 繼續(xù)初始化,繼續(xù)執(zhí)行 initializeBean 方法。
  5. 在 initializeBean 方法中,執(zhí)行其他的各種后置處理器,包括 AsyncAnnotationBeanPostProcessor,此時調(diào)用的是 AsyncAnnotationBeanPostProcessor 的 postProcessAfterInitialization 方法,在該方法中為 AService 生成了代理對象。
  6. 在 initializeBean 方法執(zhí)行完成之后,AService 會繼續(xù)去檢查最終的 Bean 是不是還是一開始的 Bean,如果不是,就去檢查當前 Bean 有沒有被其他 Bean 引用過,如果被引用過,就會拋出來異常,也就是上圖大家看到的異常信息。

好啦,這就是松哥和大家分享的三種 Spring 默認無法解決的循環(huán)依賴,其實也不是無法解決,需要一些額外配置也能解決,當然,這些額外配置并非本文重點,松哥后面再來和大家介紹~

另外最近兩篇關(guān)于循環(huán)依賴的文章都還沒有涉及到源碼分析,大家先把思路整清楚,后面松哥再出源碼分析的文章~文章來源地址http://www.zghlxwxcb.cn/news/detail-583918.html

到了這里,關(guān)于Spring 能解決所有循環(huán)依賴嗎?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 三級緩存---解決 Spring 循環(huán)依賴

    三級緩存---解決 Spring 循環(huán)依賴

    首先,什么是循環(huán)依賴?這個其實好理解,就是兩個 Bean 互相依賴,類似下面這樣: \\\"\\\"\\\" \\\"\\\"\\\" AService 和 BService 互相依賴: 一般來說,循環(huán)依賴有三種不同的形態(tài),上面就是其中一種。 另外兩種分別是三者依賴,如下圖: 這種循環(huán)依賴一般隱藏比較深,不易發(fā)覺。 還有自我依

    2024年02月16日
    瀏覽(23)
  • Spring如何解決循環(huán)依賴問題

    循環(huán)依賴問題在Spring中主要有三種情況: (1)通過構(gòu)造方法進行依賴注入時產(chǎn)生的循環(huán)依賴問題。 (2)通過setter方法進行依賴注入且是在多例(原型)模式下產(chǎn)生的循環(huán)依賴問題。 (3)通過setter方法進行依賴注入且是在單例模式下產(chǎn)生的循環(huán)依賴問題。 在Spring中,只有第

    2024年02月06日
    瀏覽(17)
  • Spring怎么解決循環(huán)依賴問題?

    Spring怎么解決循環(huán)依賴問題?

    循環(huán)依賴是指 一個或多個對象之間存在直接或間接的依賴關(guān)系,這種依賴關(guān)系構(gòu)成一個環(huán)形調(diào)用 , 舉個例子 : A 依賴B , B依賴C , C依賴A , 這樣就形成了循環(huán)依賴; ? ①構(gòu)造器的循環(huán)依賴:這種依賴spring是處理不了的,直接拋出BeanCurrentlyInCreationException異常。 ②單例模式下的se

    2024年02月08日
    瀏覽(25)
  • Spring 是如何解決循環(huán)依賴的

    Spring 是如何解決循環(huán)依賴的

    1.什么是循環(huán)依賴? 所謂的循環(huán)依賴是指,A 依賴 B,B 又依賴 A,它們之間形成了循環(huán)依賴?;蛘呤?A 依賴 B,B 依賴 C,C 又依賴 A。它們之間的依賴關(guān)系如下: 2.通過手寫代碼演示理解Spring循環(huán)依賴 DEMO: 為什么需要二級緩存? 一級緩存和二級緩存相比: 二級緩存只要是為了分

    2024年02月03日
    瀏覽(19)
  • spring解決循環(huán)依賴的三級緩存

    實例化,對應(yīng)方法:AbstractAutowireCapableBeanFactory中的createBeanInstance方法,簡單理解就是new了一個對象。 屬性注入,對應(yīng)方法:AbstractAutowireCapableBeanFactory的populateBean方法,為實例化中new出來的對象填充屬性和注入依賴。 初始化,對應(yīng)方法:AbstractAutowireCapableBeanFactory的initialize

    2024年02月03日
    瀏覽(24)
  • Spring 怎么解決循環(huán)依賴的呢?

    Spring 怎么解決循環(huán)依賴的呢?

    Spring 循環(huán)依賴:簡單說就是自己依賴自己,或者和別的 Bean 相互依賴。 只有單例的 Bean 才存在循環(huán)依賴的情況, 原型 (Prototype)情況下,Spring 會直接拋出異常。原因很簡單,AB 循環(huán)依賴,A 實例化的時候,發(fā)現(xiàn)依賴 B,創(chuàng)建 B 實例,創(chuàng)建 B 的時候發(fā)現(xiàn)需要 A,創(chuàng)建 A1 實例……

    2024年02月09日
    瀏覽(31)
  • Spring——三級緩存解決循環(huán)依賴詳解

    Spring——三級緩存解決循環(huán)依賴詳解

    就是在Bean生成流程中保存Bean對象三種形態(tài)的三個Map集合,如下: 用來解決什么問題? 這個大家應(yīng)該熟知了,就是循環(huán)依賴 什么是循環(huán)依賴? 就像下面這樣,AService 中注入了BService ,而BService 中又注入了AService ,這就是循環(huán)依賴 這幾個問題我們結(jié)合源碼來一起看一下 : 三級

    2024年02月03日
    瀏覽(39)
  • [Spring] 三級緩存解決循環(huán)依賴詳解

    [Spring] 三級緩存解決循環(huán)依賴詳解

    注冊一個bean對象的過程: Spring掃描class得到BeanDefinition – 根據(jù)得到的BeanDefinition去生成bean – 現(xiàn)根據(jù)class推斷構(gòu)造方法 – 根據(jù)推斷出來的構(gòu)造方法,反射,得到一個對象 – 填充初始對象中的屬性(依賴注入) – 如果原始對象種的某個方法被AOP了,那么要根據(jù)原始對象生成一

    2024年02月15日
    瀏覽(22)
  • 【spring6】解決循環(huán)依賴的機理

    【spring6】解決循環(huán)依賴的機理

    ????????循環(huán)依賴:A對象中有B屬性。B對象中有A屬性。比如:丈夫類Husband,妻子類Wife。Husband中有Wife的引用。Wife中有Husband的引用。 ? ? ? ? 解決:至少一個類采用set注入?+ singleton模式。 ? ? ? ? 原因:這種方式可以做到將“實例化Bean”和“給Bean屬性賦值”這兩個動作

    2024年04月26日
    瀏覽(29)
  • Spring 是如何解決循環(huán)依賴問題的?

    Spring 是如何解決循環(huán)依賴問題的?

    提示:這里簡述項目相關(guān)背景: 例如:項目場景:示例:通過藍牙芯片(HC-05)與手機 APP 通信,每隔 5s 傳輸一批傳感器數(shù)據(jù)(不是很大) ????????我們都知道,如果在代碼中,將 兩個或多個 Bean 互相之間持有對方的引用 就會發(fā)生循環(huán)依賴。循環(huán)的依賴將會導(dǎo)致注入死循環(huán),這

    2024年02月13日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包