亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring無(wú)法解決循環(huán)依賴(lài)的五種場(chǎng)景分析

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

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

1. 問(wèn)題復(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í)例化階段完成依賴(lài)注入,而此時(shí) Bean 尚未放入三級(jí)緩存。
  • 生命周期沖突:

3. 解決方案

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

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

1. 問(wèn)題復(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 官方限制:明確說(shuō)明不處理原型 Bean 的循環(huán)依賴(lài)。

3. 解決方案

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

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

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

1. 問(wèn)題復(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í)序問(wèn)題@Async 通過(guò)后置處理器生成代理,可能破壞三級(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ì)異步方法所在類(lèi)使用接口代理
@Async
public interface AsyncService {
    void asyncMethod();
}
 
@Service
public class AsyncServiceImpl implements AsyncService { /* ... */ }
  • 方案 2:在注入點(diǎn)添加 @Lazy
@Autowired @Lazy private AsyncServiceA serviceA;

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

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

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

2. 原理分析

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

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

3. 解決方案

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

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

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

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

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

@Component
public class CustomProcessor implements BeanPostProcessor {
    @Autowired private ServiceX x; // 依賴(lài)其他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();
      // ...
  }

六、終極解決方案工具箱 

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

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

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

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

  2. 依賴(lài)倒置原則:面向接口編程

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

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

相關(guān)文章

  • java多線程編程之使用Synchronized關(guān)鍵字同步類(lèi)方法

    java多線程編程之使用Synchronized關(guān)鍵字同步類(lèi)方法

    JAVA中要想解決“臟數(shù)據(jù)”的問(wèn)題,最簡(jiǎn)單的方法就是使用synchronized關(guān)鍵字來(lái)使run方法同步,看下面的代碼,只要在void和public之間加上synchronized關(guān)鍵字
    2014-01-01
  • java8 BigDecimal類(lèi)型的List求和方式

    java8 BigDecimal類(lèi)型的List求和方式

    這篇文章主要介紹了java8 BigDecimal類(lèi)型的List求和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-11-11
  • 詳解Java如何實(shí)現(xiàn)基于Redis的分布式鎖

    詳解Java如何實(shí)現(xiàn)基于Redis的分布式鎖

    在不同進(jìn)程需要互斥地訪問(wèn)共享資源時(shí),分布式鎖是一種非常有用的技術(shù)手段。這篇文章運(yùn)用圖文和實(shí)例代碼介紹了Java如何實(shí)現(xiàn)基于Redis的分布式鎖,文章介紹的很詳細(xì),對(duì)Java和Redis剛興趣的朋友們可以參考借鑒,下面來(lái)一起看看。
    2016-08-08
  • Java陷阱之a(chǎn)ssert關(guān)鍵字詳解

    Java陷阱之a(chǎn)ssert關(guān)鍵字詳解

    這篇文章詳細(xì)介紹了Java陷阱之a(chǎn)ssert關(guān)鍵字,有需要的朋友可以參考一下
    2013-09-09
  • Spring中Bean的加載與SpringBoot的初始化流程詳解

    Spring中Bean的加載與SpringBoot的初始化流程詳解

    這篇文章主要介紹了Spring中Bean的加載與SpringBoot的初始化流程詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • springboot post接口接受json時(shí),轉(zhuǎn)換為對(duì)象時(shí),屬性都為null的解決

    springboot post接口接受json時(shí),轉(zhuǎn)換為對(duì)象時(shí),屬性都為null的解決

    這篇文章主要介紹了springboot post接口接受json時(shí),轉(zhuǎn)換為對(duì)象時(shí),屬性都為null的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java如何基于EasyExcel實(shí)現(xiàn)導(dǎo)入數(shù)據(jù)校驗(yàn)并生成錯(cuò)誤信息Excel

    Java如何基于EasyExcel實(shí)現(xiàn)導(dǎo)入數(shù)據(jù)校驗(yàn)并生成錯(cuò)誤信息Excel

    這篇文章主要介紹了Java如何基于EasyExcel實(shí)現(xiàn)導(dǎo)入數(shù)據(jù)校驗(yàn)并生成錯(cuò)誤信息Excel,為了優(yōu)化項(xiàng)目中的文件導(dǎo)入功能,考慮構(gòu)建一個(gè)基于EasyExcel的通用Excel導(dǎo)入框架,主要解決導(dǎo)入數(shù)據(jù)的校驗(yàn)問(wèn)題,避免業(yè)務(wù)代碼中堆積大量校驗(yàn)邏輯,需要的朋友可以參考下
    2024-09-09
  • SpringBoot內(nèi)部外部配置文件加載順序解析

    SpringBoot內(nèi)部外部配置文件加載順序解析

    這篇文章主要介紹了SpringBoot內(nèi)部外部配置文件加載順序解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Mybatis一對(duì)多與多對(duì)一查詢(xún)處理詳解

    Mybatis一對(duì)多與多對(duì)一查詢(xún)處理詳解

    這篇文章主要給大家介紹了關(guān)于Mybatis一對(duì)多與多對(duì)一查詢(xún)處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java設(shè)計(jì)模式中的外觀模式詳解

    Java設(shè)計(jì)模式中的外觀模式詳解

    外觀模式為多個(gè)復(fù)雜的子系統(tǒng),提供了一個(gè)一致的界面,使得調(diào)用端只和這個(gè)接口發(fā)生調(diào)用,而無(wú)須關(guān)系這個(gè)子系統(tǒng)內(nèi)部的細(xì)節(jié)。本文將通過(guò)示例詳細(xì)為大家講解一下外觀模式,需要的可以參考一下
    2023-02-02

最新評(píng)論