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

Spring無法解決循環(huán)依賴的五種場景分析

 更新時(shí)間:2025年05月26日 10:50:55   作者:霧緣枯  
本文詳細(xì)分析Spring框架中五類循環(huán)依賴問題(構(gòu)造器注入、原型作用域、@Async、配置類、BeanPostProcessor),提出應(yīng)急方案如@Lazy、重構(gòu)設(shè)計(jì),并強(qiáng)調(diào)通過單一職責(zé)、依賴倒置等設(shè)計(jì)原則避免循環(huán)依賴,需要的朋友可以參考下

一、構(gòu)造器注入引發(fā)的循環(huán)依賴

1. 問題復(fù)現(xiàn)

@Component
public class ServiceA {
    private final ServiceB serviceB;
    
    @Autowired
    public ServiceA(ServiceB serviceB) { // 構(gòu)造器注入
        this.serviceB = serviceB;
    }
}
 
@Component
public class ServiceB {
    private final ServiceA serviceA;
    
    @Autowired
    public ServiceB(ServiceA serviceA) { // 構(gòu)造器注入
        this.serviceA = serviceA;
    }
}

報(bào)錯(cuò)信息:Requested bean is currently in creation: Is there an unresolvable circular reference?

2. 原理分析

  • 三級(jí)緩存失效:構(gòu)造器注入要求在實(shí)例化階段完成依賴注入,而此時(shí) Bean 尚未放入三級(jí)緩存。
  • 生命周期沖突:

3. 解決方案

  • 方案 1:將其中一個(gè) Bean 改為 Setter / 字段注入
  • 方案 2:使用 `@Lazy` 延遲加載
@Autowired
  public ServiceA(@Lazy ServiceB serviceB) { 
      this.serviceB = serviceB;
  }

二、原型(Prototype)作用域的循環(huán)依賴

1. 問題復(fù)現(xiàn)

@Scope("prototype")
@Component
public class PrototypeA {
    @Autowired private PrototypeB b;
}
 
@Scope("prototype")
@Component
public class PrototypeB {
    @Autowired private PrototypeA a;
}

2. 原理分析

  • 緩存機(jī)制不生效:原型 Bean 不會(huì)存入三級(jí)緩存,每次請(qǐng)求都創(chuàng)建新實(shí)例。

  • Spring 官方限制:明確說明不處理原型 Bean 的循環(huán)依賴。

3. 解決方案

  • 重構(gòu)設(shè)計(jì):避免原型 Bean 之間的循環(huán)依賴

  • 改用單例:評(píng)估是否真的需要原型作用域

三、@Async 注解導(dǎo)致的代理沖突

1. 問題復(fù)現(xiàn)

@Service
public class AsyncServiceA {
    @Autowired private AsyncServiceB serviceB;
    
    @Async
    public void asyncMethod() { /* ... */ }
}
 
@Service
public class AsyncServiceB {
    @Autowired private AsyncServiceA serviceA;
}

2. 原理分析

  • 代理時(shí)序問題@Async 通過后置處理器生成代理,可能破壞三級(jí)緩存機(jī)制。

  • 典型錯(cuò)誤棧

BeanCreationException: Error creating bean with name 'asyncServiceA': 
Bean with name 'asyncServiceA' has been injected into other beans [...] in their raw version as part of a circular reference.

3. 解決方案

  • 方案 1:對(duì)異步方法所在類使用接口代理
@Async
public interface AsyncService {
    void asyncMethod();
}
 
@Service
public class AsyncServiceImpl implements AsyncService { /* ... */ }
  • 方案 2:在注入點(diǎn)添加 @Lazy
@Autowired @Lazy private AsyncServiceA serviceA;

四、Configuration 類之間的循環(huán)依賴

1. 問題復(fù)現(xiàn)

@Configuration
public class ConfigA {
    @Autowired private ConfigB configB;
}
 
@Configuration
public class ConfigB {
    @Autowired private ConfigA configA;
}

2. 原理分析

  • 配置類加載順序:配置類需要優(yōu)先初始化,無法通過常規(guī)循環(huán)依賴解決。

  • Spring 限制@Configuration 類被視為特殊 Bean,其代理機(jī)制與普通 Bean 不同。

3. 解決方案

  • 重構(gòu)配置類:合并相關(guān)配置

  • 使用 @DependsOn:明確指定加載順序

@Configuration
@DependsOn("configB")
public class ConfigA { /* ... */ }

五、自定義 BeanPostProcessor 引發(fā)的沖突

1. 問題復(fù)現(xiàn)

@Component
public class CustomProcessor implements BeanPostProcessor {
    @Autowired private ServiceX x; // 依賴其他Bean
}

2. 原理分析

  • 處理器加載時(shí)序BeanPostProcessor 需要優(yōu)先初始化,此時(shí)普通 Bean 尚未創(chuàng)建。

  • Spring 啟動(dòng)流程

3. 解決方案

  • 避免在 BeanPostProcessor 中注入其他 Bean

  • 使用延遲注入

private ObjectProvider<ServiceX> xProvider;
  
  public Object postProcessBeforeInitialization(Object bean, String beanName) {
      ServiceX x = xProvider.getIfAvailable();
      // ...
  }

六、終極解決方案工具箱 

問題類型應(yīng)急方案根治方案
構(gòu)造器循環(huán)依賴@Lazy 注解改為 Setter 注入
原型Bean循環(huán)依賴重構(gòu)作用域引入中間類抽象依賴
AOP代理沖突接口代理模式調(diào)整切面作用順序
配置類循環(huán)依賴@DependsOn 指定順序合并配置類
BeanPostProcessor依賴ObjectProvider 延遲獲取分離處理器與業(yè)務(wù)邏輯

結(jié)語:跳出循環(huán)依賴的思維陷阱

Spring 的循環(huán)依賴處理機(jī)制體現(xiàn)了框架設(shè)計(jì)的高度智慧,但作為開發(fā)者,最優(yōu)雅的解決方案往往不是技術(shù)手段,而是架構(gòu)設(shè)計(jì)。通過以下原則可從根本上避免循環(huán)依賴:

  1. 單一職責(zé)原則:拆分臃腫的 Bean

  2. 依賴倒置原則:面向接口編程

  3. 層次化設(shè)計(jì):Controller -> Service -> Repository 的嚴(yán)格分層

以上就是Spring無法解決循環(huán)依賴的五種場景分析的詳細(xì)內(nèi)容,更多關(guān)于Spring無法解決循環(huán)依賴的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java笛卡爾積算法原理與實(shí)現(xiàn)方法詳解

    Java笛卡爾積算法原理與實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了Java笛卡爾積算法原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了笛卡爾積算法的原理及java定義與使用笛卡爾積算法的相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • SpringBoot壓縮json并寫入Redis的示例代碼

    SpringBoot壓縮json并寫入Redis的示例代碼

    由于業(yè)務(wù)需要,存入redis中的緩存數(shù)據(jù)過大,占用了10+G的內(nèi)存,內(nèi)存作為重要資源,需要優(yōu)化一下大對(duì)象緩存,所以我們需要對(duì)json進(jìn)行壓縮,本文給大家介紹了SpringBoot如何壓縮Json并寫入redis,需要的朋友可以參考下
    2024-08-08
  • 深入探討Kafka消費(fèi)者高性能調(diào)優(yōu)與實(shí)踐

    深入探討Kafka消費(fèi)者高性能調(diào)優(yōu)與實(shí)踐

    這篇文章主要為大家詳細(xì)介紹了Kafka消費(fèi)者在高負(fù)載環(huán)境下的性能優(yōu)化方案,內(nèi)容涵蓋Kafka基本原理,消費(fèi)者工作機(jī)制,源碼解析以及生產(chǎn)環(huán)境中的實(shí)戰(zhàn)案例
    2025-06-06
  • 微信小程序訂閱消息推送實(shí)戰(zhàn)圖文教程(Java?Spring?Boot?+?Redis)

    微信小程序訂閱消息推送實(shí)戰(zhàn)圖文教程(Java?Spring?Boot?+?Redis)

    訂閱消息是微信小程序提供的一種消息推送方式,用戶可以訂閱某個(gè)公眾號(hào)或小程序的消息,當(dāng)有新消息時(shí),系統(tǒng)會(huì)自動(dòng)推送通知給用戶,這篇文章主要介紹了微信小程序訂閱消息推送(Java Spring Boot+Redis)的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • Map之computeIfAbsent使用解讀

    Map之computeIfAbsent使用解讀

    `computeIfAbsent`是Java 8引入的一個(gè)Map接口方法,用于簡化在Map中獲取值的操作,如果指定的鍵不存在,它會(huì)調(diào)用提供的函數(shù)生成一個(gè)新的值,并將其與鍵關(guān)聯(lián),這種方法減少了手動(dòng)檢查和插入的樣板代碼,使代碼更加簡潔和易讀
    2025-02-02
  • Java執(zhí)行.bat文件的四種高效方法

    Java執(zhí)行.bat文件的四種高效方法

    在Windows操作系統(tǒng)中,.bat 文件是一種批處理腳本文件,它可以包含一系列命令,用于執(zhí)行特定的任務(wù),在Java開發(fā)中,.bat 文件通常用于簡化Java程序的啟動(dòng)和執(zhí)行過程,本文給大家介紹了Java執(zhí)行.bat文件的四種高效方法,需要的朋友可以參考下
    2025-08-08
  • 從千千靜聽歌詞服務(wù)器獲取lrc歌詞示例分享

    從千千靜聽歌詞服務(wù)器獲取lrc歌詞示例分享

    這篇文章主要介紹了使用PHP從千千靜聽歌詞服務(wù)器獲取lrc歌詞的方法,大家參考使用吧
    2014-01-01
  • kotlin快速入門之標(biāo)準(zhǔn)函數(shù)與靜態(tài)方法

    kotlin快速入門之標(biāo)準(zhǔn)函數(shù)與靜態(tài)方法

    學(xué)完了Kotlin的基礎(chǔ)知識(shí),是時(shí)候來來學(xué)習(xí) Kotlin的標(biāo)準(zhǔn)函數(shù)和靜態(tài)方法了,下面這篇文章主要給大家介紹了關(guān)于kotlin快速入門之標(biāo)準(zhǔn)函數(shù)與靜態(tài)方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • Java Lock接口實(shí)現(xiàn)原理及實(shí)例解析

    Java Lock接口實(shí)現(xiàn)原理及實(shí)例解析

    這篇文章主要介紹了Java Lock接口實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 淺談Java的兩種多線程實(shí)現(xiàn)方式

    淺談Java的兩種多線程實(shí)現(xiàn)方式

    本篇文章主要介紹了淺談Java的兩種多線程實(shí)現(xiàn)方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08

最新評(píng)論

江口县| 永福县| 汉沽区| 施秉县| 龙州县| 临清市| 临清市| 大埔区| 德州市| 安徽省| 灌阳县| 稷山县| 沁源县| 灵璧县| 钟祥市| 闸北区| 天门市| 通化县| 北宁市| 宜丰县| 河南省| 淳安县| 达尔| 蓬莱市| 安义县| 岳阳县| 定西市| 高雄市| 兴文县| 兴和县| 鄂托克前旗| 遵化市| 大理市| 秦皇岛市| 葫芦岛市| 镇雄县| 泗阳县| 甘德县| 巫溪县| 鹰潭市| 兰州市|