SpringBoot中的循环依赖以及解决办法
背景
在 SrpingBoot 2.5x 及更早版本中,对于单例 Bean,通过 setter 或字段注入形成的循环依赖,Spring 可利用三级缓存机制(singletonObjects,earlySingletonObjects,singletonFactories)自动解决。
但在之后的版本,也就是 2.6.0 及更高版本中,禁止了循环依赖,默认会抛出 BeanCurrentlyInCreationException 异常。
常见处理
- 临时处理
- 在 application.properties中添加
spring.main.allow-circular-references=true
- 在 application.properties中添加
- 使用 @Lazy注解
- 通过对报错的分析,找到其中的一个节点,并对注入点(字段/构造器参数)添加 @Lazy。
- 可以快速缓解问题,但对于依赖关系复杂难以立即调整
- 改用 Setter/字段注入
- 将循环依赖链中某些 Bean 的注入方式从构造器注入改为 Setter 方法注入或字段注入
@Autowiredprivate A a;改为private A a;@Autowiredpublic 构造方法(A a){this.a = a;}
- 将循环依赖链中某些 Bean 的注入方式从构造器注入改为 Setter 方法注入或字段注入
- 使用 Provider 延迟注入
- 注入
Provider<XxxService>
或ObjectProvider<XxxService>
,用时调用 get()// 使用 Jakarta EE 的 Providerprivate final Provider<MyService> myServiceProvider;public void executeService() {// 在实际需要的时候才通过 get() 方法获取 Bean 实例MyService myService = myServiceProvider.get();String result = myService.performTask();System.out.println(result);}
- 注入
- 代码重构
- 从根本上解决问题,通过提取公共逻辑到新类、应用事件驱动或调整依赖方向来彻底消除循环