首页 >文档 > spring bean如果出现循环依赖如何解决

spring bean如果出现循环依赖如何解决

Spring Bean循环依赖是Java面试高频考点,本文深度解析Spring三级缓存机制如何解决循环依赖问题。详细讲解单例模式下属性注入的解决方案,分析构造器注入、AOP代理等无法解决的场景,并提供@Lazy注解、接口分离等实用避坑技巧。包含大厂面试常见问题如三级缓存区别、原型作用域处理等,助你掌握Spring框架核心机制。附2025年最新Java面试宝典下载,涵盖阿里、腾讯等大厂真题,备考必备资料。需要面试鸭会员可享25元专属优惠,快速提升面试通过率。

2025年Java面试宝典网盘地址
提取码:9b3g(建议保存备用,涵盖大厂高频考点)

spring bean如果出现循环依赖如何解决

面试鸭返利网

什么是Spring Bean循环依赖?

循环依赖就是两个或多个Bean相互引用,比如A依赖B,B又反过来依赖A,形成"鸡生蛋蛋生鸡"的死循环。这种情况会导致Spring容器在初始化时抛出BeanCurrentlyInCreationException,直接影响项目启动。

面试官特别喜欢问这个问题,因为它既考察IOC容器底层机制,又涉及实际开发经验。

Spring如何解决循环依赖?

三级缓存机制

Spring通过三级缓存来破解这个困局:

  1. 一级缓存(单例池):存放完全初始化好的Bean
  2. 二级缓存(早期曝光对象):存放半成品Bean(已实例化但未初始化)
  3. 三级缓存(工厂缓存):存放Bean工厂对象

具体处理流程分三步走:

  1. 创建A时先往三级缓存注册工厂
  2. 填充属性发现需要B,触发B的创建
  3. B在填充属性时又从三级缓存拿到A的早期引用

面试鸭返利网

关键点:必须是单例+属性注入

这里有个重要前提——必须使用属性注入方式。如果是构造器注入,Spring也无能为力,因为要创建Bean必须先完成构造器调用,而构造参数中的依赖此时还未创建。

哪些情况解决不了?

1. 构造器注入死局

// 这种写法会导致启动失败
@Service
public class A {
    private final B b;
    public A(B b) { this.b = b; }
}

@Service 
public class B {
    private final A a;
    public B(A a) { this.a = a; }
}

2. AOP代理的陷阱

如果循环依赖的Bean需要生成代理对象(比如@Async、@Transactional等场景),必须保证:

  • 使用CGLIB代理(默认已支持)
  • 不要强制指定为JDK动态代理

3. @DependsOn连环套

当通过@DependsOn手动指定依赖顺序时,如果形成循环链,Spring会直接拒绝创建。

开发中的避坑指南

  1. 尽量避免循环依赖:出现循环依赖往往意味着设计有问题,推荐使用ApplicationContext.getBean()延迟获取
  2. 使用@Lazy注解:在注入点添加@Lazy,让依赖变成延迟加载
  3. 接口分离原则:将公共方法抽到单独接口,减少直接耦合
  4. 架构审查:定期用SonarQube等工具检测循环依赖

面试鸭返利网

高频面试考点

  1. 三级缓存各自存什么?为什么需要三级而不是两级?
  2. 原型(prototype)作用域的Bean能否解决循环依赖?为什么?
  3. Spring Boot中如何处理循环依赖?和Spring Framework处理方式有何不同?
  4. 如何快速定位项目中的循环依赖?

如果大家在准备面试时需要购买面试鸭会员,可以通过面试鸭返利网联系我,可享25元专属返利。更多技术干货可以下载开头的面试宝典,覆盖最新大厂真题。

如果你想获取更多关于面试鸭的优惠信息,可以访问面试鸭返利网面试鸭优惠网,了解最新的优惠活动和返利政策。

🎯 立即加入面试鸭会员 →

今日有支付宝大红包赶快领,手慢无

支付宝红包二维码

支付宝扫码领取1-8元无门槛红包

支付宝红包二维码