Spring循环依赖是开发中常见问题,当两个Bean相互依赖时会形成闭环导致启动失败。Spring通过三级缓存机制解决循环依赖:一级缓存存储完整Bean,二级缓存存储半成品Bean,三级缓存存储Bean工厂对象。核心原理是提前暴露半成品Bean,打破依赖死锁。但构造器注入、原型Bean和@Async代理场景无法解决。实际开发建议使用Setter注入、代码重构或@Lazy延迟加载来避免循环依赖。理解三级缓存机制能帮助开发者快速定位Bean创建异常,提升系统稳定性。
💡 2025年Java面试宝典重磅分享:
🔗 百度网盘链接 提取码:9b3g
(建议保存备用)
当我们说 Spring循环依赖,本质上是指两个或多个Bean相互依赖,形成闭环。比如Bean A依赖Bean B,而Bean B反过来又依赖Bean A。这种场景在项目开发中其实挺常见的,尤其是在业务模块划分不够清晰时。
@Service
public class ServiceA {
@Autowired
private ServiceB serviceB; // A依赖B
}
@Service
public class ServiceB {
@Autowired
private ServiceA serviceA; // B依赖A
}
这时候启动Spring容器,系统直接抛BeanCurrentlyInCreationException
错误!那Spring到底怎么破这个局?核心秘密就在三级缓存机制里。
先看Spring容器的三个核心缓存结构:
ObjectFactory
)放入三级缓存(暴露半成品A)getObject()
得到A的代理对象(半成品)🔥 关键点:
Spring通过提前暴露半成品Bean(三级缓存),打破了循环依赖的死锁。就像两人打架各退一步,先给对方一个"临时版本"用着。
三级缓存虽强,但也有硬伤:
构造器注入循环依赖(直接报错)
public class A {
public A(B b) { ... } // 构造器依赖B
}
原因:必须拿到B才能实例化A,但B也需要A... 死锁无解!
原型Bean(prototype)的循环依赖
每次都要新实例化,无法用缓存机制兜底
@Async代理对象循环依赖
动态代理机制导致三级缓存拿到的对象和最终对象不一致
虽然Spring提供了解决方案,但实际开发中还是建议:
重构代码结构
使用事件驱动(ApplicationEvent)或中介者模式解耦
优先用Setter/Field注入
避免构造器注入导致的硬死锁
模块化拆分
用@Lazy
延迟加载非核心依赖
@Autowired @Lazy
private ServiceB serviceB; // 暂时不初始化
你可能疑惑:二级缓存不够用吗?来看个特殊场景:
@Service
public class UserService {
@Autowired
private RoleService roleService; // 依赖角色服务
}
@Service
public class LogService {
@Autowired
private UserService userService; // 依赖用户服务
}
@Service
public class RoleService {
@Autowired
private UserService userService; // 依赖用户服务
}
此时存在多个Bean依赖同一个半成品UserService。如果只有二级缓存:
三级缓存通过工厂模式保证:多次获取半成品Bean时,返回的是同一个代理对象,避免对象不一致问题。
当面试官问Spring循环依赖解决方案时,分三步回答:
📢 会员福利提示:
如果需要开通「面试鸭」会员刷真题,记得通过 面试鸭返利网 下单!返利25元,真实有效(已帮200+程序员省钱):
| 核心机制 | 作用 | 注意事项 | |----------------|----------------------------|----------------------------| | 三级缓存 | 暴露半成品Bean | 只对单例Bean有效 | | ObjectFactory | 延迟生成代理对象 | 解决AOP导致的对象不一致问题 | | 构造器注入 | 无法解决循环依赖 | 需改用Setter注入 | | @Lazy | 延迟初始化依赖 | 适用于非核心链式依赖 |
理解Spring循环依赖底层原理,不仅为了面试通关,更能帮你在实际开发中快速定位Bean创建异常。毕竟谁没在深夜被BeanCurrentlyInCreationException
折磨过呢?🙃
扫码联系我返利
(当前返利8元,金额随官方实际价格波动,最好提前咨询)
面试鸭小程序码
美团大额优惠券,给自己加个鸡腿吧!
今日有支付宝大红包赶快领,手慢无
支付宝扫码领取1-8元无门槛红包