
循环依赖两个或多个 Bean 互相注入A依赖BB依赖ASpring 默认只能解决单例 Bean 的 setter/字段注入循环依赖构造器注入、多例、代理场景会直接报错。我会分场景解决方案从最简单到最复杂讲清楚。一、先判断你的循环依赖属于哪种1. 最常见单例 Bean 字段/setter 注入无报错Spring自动解决无需处理。ServicepublicclassA{AutowiredprivateBb;// 字段注入}ServicepublicclassB{AutowiredprivateAa;}✅正常运行Spring 三级缓存天然支持。2. 构造器注入循环依赖必报错这是最常见的报错场景ServicepublicclassA{// 构造器注入 A 依赖 BpublicA(Bb){}}ServicepublicclassB{// 构造器注入 B 依赖 ApublicB(Aa){}}❌ 报错Requested bean is currently in creation解决方案3种最优解方案1改用字段/Autowired 注入最简单直接把构造器注入改成字段注入Spring 自动解决。方案2使用Lazy懒加载推荐在构造器参数上加Lazy创建临时代理对象打破循环ServicepublicclassA{publicA(LazyBb){// 关键Lazythis.bb;}}ServicepublicclassB{publicB(Aa){this.aa;}}方案3使用ApplicationContext手动获取 BeanServicepublicclassAimplementsApplicationContextAware{privateBb;OverridepublicvoidsetApplicationContext(ApplicationContextctx){this.bctx.getBean(B.class);// 手动获取}}3. 多例prototypeBean 循环依赖必报错Spring不解决多例循环依赖无三级缓存支持。解决方案放弃多例改成单例90%场景适用手动创建对象不用 Spring 管理依赖使用Provider延迟注入ComponentScope(prototype)publicclassA{AutowiredprivateObjectProviderBbProvider;publicBgetB(){returnbProvider.getObject();}}4. 代理类导致的循环依赖AOP/事务开启 AOP/Transactional后Bean 被代理默认三级缓存会失效报错。解决方案方案1启动类加配置最省事SpringBootApplicationpublicclassApp{publicstaticvoidmain(String[]args){// 允许循环依赖System.setProperty(spring.main.allow-circular-references,true);SpringApplication.run(App.class,args);}}方案2yml 配置spring:main:allow-circular-references:true5. 终极方案重构代码最规范推荐循环依赖本质是代码设计不合理最好从根源解决抽取公共类把 A、B 共用逻辑抽到 CA、B 都依赖 C使用事件/观察者模式解耦互相依赖使用方法调用不用注入 Bean直接调用方法示例抽取公共类// 公共逻辑ServicepublicclassC{}ServicepublicclassA{AutowiredprivateCc;}ServicepublicclassB{AutowiredprivateCc;}✅ 彻底消除循环依赖代码更优雅。二、快速排查工具如果你不知道哪里循环依赖开启日志logging:level:org.springframework:DEBUG日志会打印完整依赖链直接定位报错 Bean。三、总结按场景选择方案依赖场景是否报错解决方案单例字段注入否无需处理构造器注入是Lazy/ 字段注入多例Bean是改单例 /ObjectProviderAOP/事务代理是开启allow-circular-references所有场景-重构代码最优核心记住Spring只自动解决单例字段/setter 注入的循环依赖构造器注入用Lazy最快解决生产环境优先重构代码不要依赖配置强行开启循环依赖