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 或重构代码解除循环
相关推荐
红烧大青虫7 小时前
HarmonyOS应用开发实战:小事记 - UIAbility 的冷启动/热启动/后台启动三种场景与 launchParam 解析
后端·华为·harmonyos·鸿蒙系统
码事漫谈7 小时前
AI Token 缓存:命中省 10 倍,不命中白扔钱
后端
CRMEB系统商城7 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
65岁退休Coder7 小时前
LangChain v1.3.4 笔记 - 04 Agent 中间件
后端
keyipatience8 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
神奇小汤圆8 小时前
一个接口多个实现,Spring 怎么"适配多场景"?
后端
花开彼岸天~8 小时前
鸿蒙原生开发手记:徒步迹 - 自定义组件开发规范
后端·华为·harmonyos·鸿蒙系统
weixin_408099679 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
钱六两9 小时前
#3、SpringAI 接入deepSeek大模型(喂饭版)
java·spring boot·ai编程
Suhan429 小时前
IDEA 设置启动参数和环境变量
spring boot·spring·编辑器·idea