最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

你知道Spring如何解決所有循環(huán)依賴的嗎

 更新時間:2023年07月20日 10:20:02   作者:江南一點雨  
這篇文章主要來和大家聊聊Spring?能解決所有循環(huán)依賴嗎,文中的示例代碼講解詳細,對我們學習Spring有一定的幫助,需要的小伙伴可以參考一下

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

看了上篇文章的小伙伴,對于 Spring 解決循環(huán)依賴的思路應該有一個大致了解了,今天我們再來看一看,按照上篇文章介紹的思路,有哪些循環(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;
????}
}

運行時報錯如下:

原因分析:

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

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

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

@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)依賴運行時也會報錯,報錯信息如下(跟前面報錯信息一樣):

原因分析:

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;
}

報錯信息如下:

其實大家從這段報錯信息中也能看出來個七七八八:在 BService 中注入了 AService 的原始對象,但是 AService 在后續(xù)的處理流程中被 AOP 代理了,產(chǎn)生了新的對象,導致 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í)行流程。

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

到此這篇關(guān)于你知道Spring如何解決所有循環(huán)依賴的嗎的文章就介紹到這了,更多相關(guān)Spring解決循環(huán)依賴內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java substring 截取字符串的方法

    java substring 截取字符串的方法

    這篇文章主要介紹了java substring 截取字符串的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • 使用IntelliJ?IDEA創(chuàng)建簡單的Java?Web項目完整步驟

    使用IntelliJ?IDEA創(chuàng)建簡單的Java?Web項目完整步驟

    這篇文章主要介紹了如何使用IntelliJ?IDEA創(chuàng)建一個簡單的JavaWeb項目,實現(xiàn)登錄、注冊和查看用戶列表功能,使用Servlet和JSP技術(shù),文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-01-01
  • SpringBoot中JSON工具類JsonUtils的實踐教學

    SpringBoot中JSON工具類JsonUtils的實踐教學

    Spring?Boot?項目里,JSON?工具類是每個?Service?都要寫的東西,JsonUtils的核心是一個統(tǒng)一接口覆蓋三套?JSON?引擎,本文主要介紹了JsonUtils在SpringBoot項目中的具體應用,希望對大家有所幫助
    2026-06-06
  • 你還在用Synchronized?Atomic你了解不?

    你還在用Synchronized?Atomic你了解不?

    這篇文章主要介紹了你還在用Synchronized?Atomic你了解不? 文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12
  • SpringBoot如何使用注解進行XSS防御

    SpringBoot如何使用注解進行XSS防御

    在SpringBoot中,可以通過自定義@XSS注解和實現(xiàn)XSSValidator類來防御XSS攻擊,此方法適用于GET和POST請求,通過在方法參數(shù)或?qū)嶓w類屬性上添加@XSS注解,并結(jié)合@Valid或@Validated注解使用,有效攔截潛在的XSS腳本,保障應用安全
    2024-11-11
  • IDEA:Git stash 暫存分支修改的實現(xiàn)代碼

    IDEA:Git stash 暫存分支修改的實現(xiàn)代碼

    這篇文章主要介紹了IDEA:Git stash 暫存分支修改的實現(xiàn)代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Java字符串工具類從原生到第三方庫的高效實踐詳解

    Java字符串工具類從原生到第三方庫的高效實踐詳解

    字符串是我們在編程中最常使用的一種數(shù)據(jù)類型,Java中用類來描述字符串,其中最常用的字符串處理類是String,這篇文章主要介紹了Java字符串工具類從原生到第三方庫的高效實踐的相關(guān)資料,需要的朋友可以參考下
    2025-08-08
  • 快速解決Hash碰撞沖突的方法小結(jié)

    快速解決Hash碰撞沖突的方法小結(jié)

    這篇文章主要介紹了快速解決Hash碰撞沖突的方法小結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 簡單了解java中int和Integer的區(qū)別

    簡單了解java中int和Integer的區(qū)別

    這篇文章主要介紹了簡單了解java中int和Integer的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • 圖解Java?ReentrantLock的條件變量Condition機制

    圖解Java?ReentrantLock的條件變量Condition機制

    想必大家都使用過wait()和notify()這兩個方法把,他們主要用于多線程間的協(xié)同處理。而RenentrantLock也支持這樣條件變量的能力,而且相對于synchronized?更加強大,能夠支持多個條件變量,本文就來詳細說說
    2022-10-10

最新評論

邵东县| 定州市| 滨海县| 利津县| 日照市| 台山市| 义马市| 宁夏| 锡林浩特市| 茶陵县| 鸡西市| 镇康县| 邵武市| 晴隆县| 甘南县| 兰考县| 通河县| 汝阳县| 华亭县| 泸州市| 山丹县| 乌兰察布市| 泸定县| 宽城| 嘉定区| 河南省| 中超| 阳东县| 无极县| 桐乡市| 吴江市| 汝阳县| 吉水县| 荆门市| 合山市| 河北省| 东港市| 黑山县| 行唐县| 崇信县| 陆河县|