spring如何解决循环依赖

Spring 解决循环依赖核心依靠:三级缓存 + 提前暴露早期半成品 Bean ,仅支持单例、构造器注入以外的场景。


一、什么是循环依赖

两个或多个 Bean 互相依赖:

java 复制代码
@Component
public class A {
  @Autowired
  private B b;
}

@Component
public class B {
  @Autowired
  private A a;
}

二、核心原理:三级缓存

Spring 容器维护三个 Map(三级缓存):

  1. singletonObjects(一级缓存)

    • 存放完全初始化好的单例 Bean
  2. earlySingletonObjects(二级缓存)

    • 存放实例化完成,但未填充属性、未初始化的早期 Bean
  3. singletonFactories(三级缓存)

    • 存放创建早期 Bean 的ObjectFactory,用于获取早期引用

三、解决流程(A ↔ B)

  1. 创建 A:实例化 A,将 A 的 ObjectFactory 放入三级缓存,暴露早期引用
  2. 填充 A 属性:发现依赖 B,去创建 B
  3. 创建 B:实例化 B,将 B 的 ObjectFactory 放入三级缓存
  4. 填充 B 属性:发现依赖 A,从缓存获取 A:
    • 先查一级缓存(无)
    • 查二级缓存(无)
    • 查三级缓存,拿到 A 的 ObjectFactory,获取早期 A 对象,放入二级缓存,并删除三级缓存
  5. B 完成属性填充 + 初始化,加入一级缓存
  6. 回到 A,拿到完整 B,完成 A 初始化,加入一级缓存

四、哪些情况无法解决

Spring 无法解决以下循环依赖,启动报错:

  1. 构造器注入循环依赖

    java 复制代码
    @Component
    public class A {
      // 构造器注入 B
      public A(B b) {}
    }
    
    @Component
    public class B {
      // 构造器注入 A
      public B(A a) {}
    }

    实例化时就互相依赖,无法提前暴露。

  2. 多例(prototype)Bean

    多例不进入缓存,每次创建新实例,无法缓存提前引用。

  3. 使用 @DependsOn 显式构成循环依赖。


五、无法解决时的方案

  1. 改用 setter / 字段注入(而非构造器)

  2. 使用 @Lazy 懒加载:

    java 复制代码
    @Component
    public class A {
      @Autowired
      @Lazy
      private B b;
    }
  3. 拆分子功能,解除循环依赖

  4. 使用 ApplicationContextAwareInitializingBean 手动获取依赖


六、总结

  • 默认支持:单例 + setter / 字段注入循环依赖
  • 核心手段:三级缓存提前暴露半成品 Bean
  • 不支持 :构造器注入、多例、@DependsOn 循环
  • 优化 :优先用 @Lazy 或重构代码解除循环
相关推荐
·薯条大王6 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
CodeSheep7 小时前
稚晖君公司人事大变动,来了!
前端·后端·程序员
小满zs7 小时前
Go语言第八章(函数)
后端·go
stark张宇9 小时前
实战Go高级特性:Context超时控制、defer资源回收与Channel通信的关键避坑点
后端·go
ZJH__GO9 小时前
网络编程v4pro--实现聊天室文件传输功能
java·服务器·网络·计算机网络
程序员黑豆9 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
命运之光10 小时前
【C语言完整代码】就诊信息管理系统
java·c语言·开发语言
凤山老林10 小时前
Spring Boot @Async 线上实战:从默认配置到生产级线程池治理
java·spring boot·后端
IT_陈寒11 小时前
Vue的响应式让我原地破防,原来问题出在这
前端·人工智能·后端
marvelyu11 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库