首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

SpringBoot3.4.3为何频繁检测出循环依赖?一招快速解决它!

真没想到,阻止框架升级的不仅仅是某个框架被弃用,还有让人恶心的循环调用。

如果在启动项目时看到类似这样循环的标识,恭喜你,项目中出现循环依赖了。

循环依赖普遍出现在service层。ServiceA调用了ServiceB,ServiceB调用了ServiceC,ServiceC又调用了ServiceA,形成了一个调用上的循环。

静态代码有循环依赖,并不代表代码执行后还有循环依赖!

我想做点辩解,并想允许它的存在。

同时呢,我还有一个疑问:同样的代码,为什么历史版本没有出现循环依赖?项目升级后就出现了循环依赖?

原来是:从Spring Boot 2.6开始,默认禁止了循环依赖(spring.main.allow-circular-references=false),导致原本被允许的循环依赖在启动时直接报错。这就导致即使代码中存在隐式的循环依赖(如A依赖B,B依赖A),也会在启动时被检测并抛出异常。

原因知道了。循环依赖应该怎么解决呢?

一、临时解决方案

报错提示信息已经给出了答案。

在application.properties或application.yml中添加:

spring.main.allow-circular-references=true

如果短期内无法重构代码,可以临时允许循环引用。

或者在启动类中添加:

@SpringBootApplication

public class MyApp{

  public static void main(String[] args){

      new SpringApplicationBuilder(MyApp.class)

          .allowCircularReferences(true)

          .run(args);

  }

}

二、从程序设计上

从程序设计上调整改动有点大,看看即可。

1、重构设计,打破循环

检查Service之间的相互依赖是否必要。

考虑引入第三方服务或事件机制来解耦。

使用接口隔离原则,将大接口拆分为更小、更专注的接口。

2、使用Setter注入代替字段注入

// 例如在VoteNoticeServiceImpl中

private IClusterNoticeService clusterNoticeService;

@Autowired

publicvoidsetClusterNoticeService(IClusterNoticeService clusterNoticeService){

  this.clusterNoticeService = clusterNoticeService;

}

3、使用@Lazy注解

// 在循环依赖的一侧添加@Lazy

@Autowired

@Lazy

private IClusterNoticeService clusterNoticeService;

这三个建议在新建项目编码的时候可以考虑考虑。

三、长期建议

循环依赖通常是设计问题,建议:

1、重新审视服务层的职责划分。

2、考虑使用领域驱动设计(DDD)来明确各服务的边界。

3、对于通知类服务,可以考虑使用事件驱动架构,通过Spring事件机制解耦。

最佳实践是重构代码消除循环依赖,而不是依赖框架的宽松配置。

尴尬了,我就想依赖框架的宽松配置!

四、最后总结

如果是新项目,即可以使用长期建议,也可以从程序设计上考虑考虑。

如果是升级老项目,还是用临时解决方案吧,又快又省麻烦还少!

  • 发表于:
  • 原文链接https://page.om.qq.com/page/Oqd3zTL7ucf5TMH3iPcYkDdw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券