Springboot循环依赖的原因及解决

 更新时间:2025年05月07日 11:05:47   作者:帝锦_li  
本文主要介绍了Spring Boot中的循环依赖问题,包括循环依赖的定义、产生原因以及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

什么是循环依赖

循环依赖(Circular Dependency) 是指两个或多个 Bean 相互直接或间接依赖,导致容器无法正常初始化这些 Bean。

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB; // ServiceA 依赖 ServiceB
}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA; // ServiceB 依赖 ServiceA
}

Spring Boot 基于 Spring 框架,其循环依赖的处理机制与 Spring 一致,但在 Spring Boot 2.6+ 版本中默认禁止了循环依赖(通过 spring.main.allow-circular-references=false)。 

产生循环依赖的原因

1.构造函数注入循环依赖

@Service
public class ServiceA {
    private final ServiceB serviceB;
    public ServiceA(ServiceB serviceB) { // 构造函数注入
        this.serviceB = serviceB;
    }
}

@Service
public class ServiceB {
    private final ServiceA serviceA;
    public ServiceB(ServiceA serviceA) { // 构造函数注入
        this.serviceA = serviceA;
    }
}
  • 直接报错:构造函数注入的循环依赖无法解决,容器启动时抛出 BeanCurrentlyInCreationException

2.Setter/Field 注入循环依赖

在spring中使用@Autowired注解标签进行自动注入,如果不加以处理,会出现循环依赖问题 。

怎么解决循环依赖

在Springboot2.5以前可以通过三级缓存解决单例 Bean 的循环依赖问题。

缓存名称职责
singletonObjects存放完全初始化好的 Bean(一级缓存)
earlySingletonObjects存放提前暴露的早期 Bean(二级缓存)
singletonFactories存放 Bean 的工厂对象(三级缓存)

以最初的ServiceA与ServiceB为例,

  • 创建 ServiceA,通过工厂将其半成品引用存入三级缓存。

  • ServiceA 注入 ServiceB,触发 ServiceB 的创建。

  • 创建 ServiceB,同样将其半成品引用存入三级缓存。

  • ServiceB 注入 ServiceA 时,从三级缓存中获取 ServiceA 的早期引用,完成 ServiceB 的初始化。

  • ServiceB 初始化完成后,ServiceA 完成依赖注入,最终初始化。

 出现循环依赖之后的几个解决思路:

1.避免循环依赖(推荐)

  • 重构代码:将公共逻辑抽离到第三个 Bean 中。

  • 使用接口或抽象类:通过面向接口编程解耦具体实现。

2. 允许循环依赖(临时方案)

在 application.properties 中显式允许循环依赖:

# Spring Boot 2.6+ 需要手动开启
spring.main.allow-circular-references=true

这种只适用于Springboot版本在2.6以上的循环依赖被禁止的情形。 

3. 使用 @Lazy 延迟加载

在其中一个依赖上添加 @Lazy,延迟注入 Bean 的初始化:

@Service
public class ServiceA {
    @Lazy
    @Autowired
    private ServiceB serviceB; // 延迟初始化 ServiceB
}

4. 调整注入方式

 优先使用 Setter/Field 注入:避免构造函数注入导致的不可解循环依赖。

@Service
public class ServiceA {
    private ServiceB serviceB;
    
    @Autowired
    public void setServiceB(ServiceB serviceB) { // Setter 注入
        this.serviceB = serviceB;
    }
}

 使用setter注入

循环依赖的局限性

  • 构造函数注入无法解决循环依赖:Spring 容器在创建 Bean 时需先完成构造函数调用,此时依赖的 Bean 尚未初始化。

  • 原型(Prototype)作用域的 Bean:Spring 不管理原型 Bean 的完整生命周期,无法解决其循环依赖。

  • AOP 代理问题:如果 Bean 被 AOP 代理(如 @Async@Transactional),可能导致循环依赖解决失败。

总结

Spring Boot 的循环依赖本质是 Spring 框架的机制问题,解决核心在于:

  • 理解三级缓存的工作原理。

  • 优先通过代码设计避免循环依赖。

  • 必要时合理使用 @Lazy 或调整注入方式。

 尽可能在设计之初就避免循环依赖

到此这篇关于Springboot循环依赖的原因及解决的文章就介绍到这了,更多相关Springboot循环依赖内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 学习Java的Date、Calendar日期操作

    学习Java的Date、Calendar日期操作

    Java开发过程中避免不了日期相关操作,这篇文章总结了一些Date、Calendar的常用方法,需要的朋友可以参考下
    2015-07-07
  • Spring XML Schema扩展机制的使用示例

    Spring XML Schema扩展机制的使用示例

    所谓整合,即在Spring的框架下进行扩展,让框架能无缝的与Spring工程配合使用。Spring设计了良好的扩展的机制,本文将对Spring的扩展方法及原理进行简单介绍。
    2021-05-05
  • 教你用Java验证服务器登录系统

    教你用Java验证服务器登录系统

    这篇文章主要介绍了教你用Java验证服务器登录系统,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-04-04
  • mybatis 集合嵌套查询和集合嵌套结果的区别说明

    mybatis 集合嵌套查询和集合嵌套结果的区别说明

    这篇文章主要介绍了mybatis 集合嵌套查询和集合嵌套结果的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java使用poi导出Excel的方法

    java使用poi导出Excel的方法

    这篇文章主要为大家详细介绍了java使用poi导出Excel的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • Java面试题冲刺第八天--Spring框架2

    Java面试题冲刺第八天--Spring框架2

    这篇文章主要为大家分享了最有价值的三道Spring框架面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • SpringBoot实现多个子域共享cookie的示例

    SpringBoot实现多个子域共享cookie的示例

    本文主要介绍了SpringBoot实现多个子域共享cookie的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Jenkins Pipeline为Kubernetes应用部署增加状态检测脚本优化

    Jenkins Pipeline为Kubernetes应用部署增加状态检测脚本优化

    这篇文章主要为大家介绍了Jenkins Pipeline为Kubernetes应用部署增加状态检测脚本优化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Java中的静态代码块使用解读

    Java中的静态代码块使用解读

    本文将深入探讨静态代码块的工作原理、使用场景以及一些最佳实践,帮助你更好地理解和应用这一特性
    2025-02-02
  • IDEA 启动 Tomcat 项目输出乱码的解决方法

    IDEA 启动 Tomcat 项目输出乱码的解决方法

    这篇文章主要介绍了IDEA 启动 Tomcat 项目输出乱码的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11

最新评论