欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot循環(huán)依賴問題案例代碼及解決辦法

 更新時(shí)間:2025年04月03日 14:50:19   作者:學(xué)亮編程手記  
在 Spring Boot 中,如果兩個(gè)或多個(gè) Bean之間存在循環(huán)依賴(即 Bean A 依賴 Bean B,而 Bean B 又依賴 Bean A),會(huì)導(dǎo)致 Spring 的依賴注入機(jī)制無法正確處理,從而拋出異常,下面給大家介紹springboot循環(huán)依賴問題及其解決辦法,感興趣的朋友一起看看吧

在 Spring Boot 中,如果兩個(gè)或多個(gè) Bean 之間存在循環(huán)依賴(即 Bean A 依賴 Bean B,而 Bean B 又依賴 Bean A),會(huì)導(dǎo)致 Spring 的依賴注入機(jī)制無法正確處理,從而拋出異常。以下是循環(huán)依賴的場景分析、案例代碼及常見的解決方法。

1. 什么是循環(huán)依賴?

概念

循環(huán)依賴是指兩個(gè)或多個(gè) Bean 相互依賴,形成一個(gè)閉環(huán)。例如:

  • 直接循環(huán)依賴
    • A 依賴 B,B 依賴 A。
  • 間接循環(huán)依賴
    • A 依賴 B,B 依賴 C,而 C 又依賴 A。

2. 循環(huán)依賴的場景案例

以下是一個(gè)簡單的直接循環(huán)依賴場景。

案例代碼 Bean A

@Component
public class BeanA {
    @Autowired
    private BeanB beanB;
    public BeanA() {
        System.out.println("BeanA Constructor");
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
    }
}

Bean B

@Component
public class BeanB {
    @Autowired
    private BeanA beanA;
    public BeanB() {
        System.out.println("BeanB Constructor");
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

啟動(dòng)類

@SpringBootApplication
public class CircularDependencyDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CircularDependencyDemoApplication.class, args);
    }
}

運(yùn)行結(jié)果

運(yùn)行時(shí),Spring 會(huì)拋出以下異常:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?

3. 解決循環(huán)依賴的常見方法

方法 1:使用 @Lazy 注解

@Lazy 注解可以延遲加載 Bean,使 Spring 在真正需要使用時(shí)才注入依賴,從而打破循環(huán)依賴。

修改代碼

在其中一個(gè)依賴上添加 @Lazy 注解:

BeanA:

@Component
public class BeanA {
    @Autowired
    @Lazy
    private BeanB beanB;
    public BeanA() {
        System.out.println("BeanA Constructor");
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
    }
}

BeanB:

@Component
public class BeanB {
    @Autowired
    private BeanA beanA;
    public BeanB() {
        System.out.println("BeanB Constructor");
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

運(yùn)行結(jié)果

程序運(yùn)行正常,輸出:

BeanA Constructor
BeanB Constructor

方法 2:使用構(gòu)造器注入解決循環(huán)依賴

Spring 無法通過構(gòu)造器注入解決循環(huán)依賴,因?yàn)樵跇?gòu)造器注入的過程中,所有依賴必須在實(shí)例化時(shí)完全注入。這種情況下,需要重新設(shè)計(jì)代碼結(jié)構(gòu)以打破循環(huán)依賴。

重構(gòu)代碼

將循環(huán)依賴重構(gòu)為單向依賴。例如,可以引入第三方協(xié)作者 Bean 來解耦。

BeanA:

@Component
public class BeanA {
    private final Helper helper;
    public BeanA(Helper helper) {
        this.helper = helper;
        System.out.println("BeanA Constructor");
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
    }
}

BeanB:

@Component
public class BeanB {
    private final Helper helper;
    public BeanB(Helper helper) {
        this.helper = helper;
        System.out.println("BeanB Constructor");
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

Helper:

@Component
public class Helper {
    public void assist() {
        System.out.println("Helper is assisting");
    }
}

運(yùn)行結(jié)果

Helper Constructor
BeanA Constructor
BeanB Constructor

通過引入 Helper,BeanABeanB 不再直接依賴彼此,循環(huán)依賴被消除。

方法 3:使用 @PostConstruct 或 Setter 注入

通過構(gòu)造器注入會(huì)導(dǎo)致循環(huán)依賴問題,但可以使用 Setter 方法注入來延遲依賴注入的時(shí)機(jī)。

修改代碼

BeanA:

@Component
public class BeanA {
    private BeanB beanB;
    public BeanA() {
        System.out.println("BeanA Constructor");
    }
    @Autowired
    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
    }
}

BeanB:

@Component
public class BeanB {
    private BeanA beanA;
    public BeanB() {
        System.out.println("BeanB Constructor");
    }
    @Autowired
    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

運(yùn)行結(jié)果

BeanA Constructor
BeanB Constructor

Setter 注入允許 Spring 在實(shí)例化 Bean 后再設(shè)置依賴,從而避免循環(huán)依賴問題。

方法 4:使用 ObjectFactory 或 Provider 進(jìn)行延遲注入

Spring 提供了 ObjectFactoryProvider 接口,用于延遲獲取 Bean,從而避免循環(huán)依賴。

修改代碼 BeanA:

@Component
public class BeanA {
    private final ObjectFactory<BeanB> beanBFactory;
    public BeanA(ObjectFactory<BeanB> beanBFactory) {
        this.beanBFactory = beanBFactory;
        System.out.println("BeanA Constructor");
    }
    public void doSomething() {
        BeanB beanB = beanBFactory.getObject();
        System.out.println("BeanA is doing something with " + beanB);
    }
}

BeanB:

@Component
public class BeanB {
    private final BeanA beanA;
    @Autowired
    public BeanB(BeanA beanA) {
        this.beanA = beanA;
        System.out.println("BeanB Constructor");
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

運(yùn)行結(jié)果

BeanA Constructor
BeanB Constructor

通過 ObjectFactory,BeanA 可以在需要時(shí)動(dòng)態(tài)獲取 BeanB,避免了循環(huán)依賴。

方法 5:使用 @DependsOn 明確加載順序

如果循環(huán)依賴是因?yàn)?Bean 的加載順序問題,可以使用 @DependsOn 指定加載順序。

修改代碼

BeanA:

@Component
@DependsOn("beanB") // 指定 BeanB 應(yīng)該先加載
public class BeanA {
    @Autowired
    private BeanB beanB;
    public BeanA() {
        System.out.println("BeanA Constructor");
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
    }
}

BeanB:

@Component
public class BeanB {
    @Autowired
    private BeanA beanA;
    public BeanB() {
        System.out.println("BeanB Constructor");
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
    }
}

運(yùn)行結(jié)果

BeanB Constructor
BeanA Constructor

4. 總結(jié)

循環(huán)依賴是常見問題,但可以通過多種方式解決:

  • 使用 @Lazy 延遲加載。
  • 重構(gòu)代碼,避免直接循環(huán)依賴。
  • 使用 Setter 注入或 @PostConstruct。
  • 使用 ObjectFactory 或 Provider 進(jìn)行延遲注入。
  • 使用 @DependsOn 明確加載順序。

推薦方案

如果可以重構(gòu)代碼,消除循環(huán)依賴本身是最佳實(shí)踐。在必要時(shí),結(jié)合 @LazyObjectFactory 來解決循環(huán)依賴問題。

到此這篇關(guān)于springboot循環(huán)依賴問題及其解決辦法的文章就介紹到這了,更多相關(guān)springboot循環(huán)依賴內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring?@Scheduled注解各參數(shù)使用以及定時(shí)任務(wù)詳解

    spring?@Scheduled注解各參數(shù)使用以及定時(shí)任務(wù)詳解

    文章詳細(xì)介紹了Spring框架中@Scheduled注解的各個(gè)參數(shù),包括cron表達(dá)式、時(shí)區(qū)、fixedDelay、fixedRate、initialDelay等,并提供了多個(gè)示例來說明這些參數(shù)的使用方法
    2024-11-11
  • Spring Event觀察者模式事件監(jiān)聽詳解

    Spring Event觀察者模式事件監(jiān)聽詳解

    這篇文章主要介紹了Java Spring Event事件監(jiān)聽詳情解析,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Java遞歸遍歷文件目錄代碼實(shí)例

    Java遞歸遍歷文件目錄代碼實(shí)例

    這篇文章主要介紹了Java遞歸遍歷文件目錄代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java躲不過設(shè)計(jì)模式的坑之代理模式詳解

    Java躲不過設(shè)計(jì)模式的坑之代理模式詳解

    設(shè)計(jì)模式看來更像是一種設(shè)計(jì)思維或設(shè)計(jì)思想,為你的項(xiàng)目工程提供方向,讓你的項(xiàng)目工程更加健壯、靈活,延續(xù)生命力。本文即將分享的是設(shè)計(jì)模式的其中一種:代理模式,感興趣的可以了解一下
    2022-09-09
  • java之jvm加載器例舉

    java之jvm加載器例舉

    在本篇文章里小編給大家介紹了關(guān)于java之jvm加載器例舉內(nèi)容,對(duì)此有需要的程序員朋友們可以參考下。
    2021-03-03
  • 解決@Async(“taskExecutor“)異步線程報(bào)錯(cuò)問題

    解決@Async(“taskExecutor“)異步線程報(bào)錯(cuò)問題

    這篇文章主要介紹了解決@Async(“taskExecutor“)異步線程報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Spring Junit單元測試加載配置文件失敗問題

    Spring Junit單元測試加載配置文件失敗問題

    這篇文章主要介紹了Spring Junit加載配置文件失敗問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java實(shí)現(xiàn)簡易生產(chǎn)者消費(fèi)者模型過程解析

    Java實(shí)現(xiàn)簡易生產(chǎn)者消費(fèi)者模型過程解析

    這篇文章主要介紹了Java實(shí)現(xiàn)簡易生產(chǎn)者消費(fèi)者模型過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • springmvc 中dao層和service層的區(qū)別說明

    springmvc 中dao層和service層的區(qū)別說明

    這篇文章主要介紹了springmvc 中dao層和service層的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java執(zhí)行shell并獲取shell輸出日志方式

    java執(zhí)行shell并獲取shell輸出日志方式

    這篇文章主要介紹了java執(zhí)行shell并獲取shell輸出日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04

最新評(píng)論