当前位置: 首页 > news >正文

如何解决spring循环依赖

这个错误提示表明Spring应用程序中存在循环依赖问题,即两个或多个Bean之间相互依赖,形成了一个闭环。在你的案例中,dataGenerationImplRegisterVersionSourceImpl这两个Bean互相引用,导致Spring无法正常创建它们。

什么是循环依赖?

当Bean A依赖于Bean B,而Bean B又依赖于Bean A时,就形成了循环依赖。例如:

// Bean A依赖B
class DataGenerationImpl {@Autowiredprivate RegisterVersionSourceImpl registerVersionSource;// ...
}// Bean B依赖A
class RegisterVersionSourceImpl {@Autowiredprivate DataGenerationImpl dataGeneration;// ...
}

Spring在创建Bean时,需要先实例化依赖的Bean。但在循环依赖的情况下,两个Bean都需要对方先创建,导致创建过程陷入死循环

为什么会报错?

从Spring Boot 2.6开始,默认禁止循环依赖spring.main.allow-circular-references=false),因为循环依赖会导致以下问题:

  1. 依赖关系不清晰:代码结构混乱,难以理解和维护。
  2. 潜在的运行时错误:可能导致空指针异常或其他意外行为。
  3. 初始化顺序问题:Bean的初始化顺序变得不可预测。

如何解决循环依赖?

1. 重构代码,消除循环依赖

这是最推荐的方法,通过以下方式解耦:

  • 提取公共逻辑到第三方Bean:将两个Bean共同依赖的逻辑提取到新的组件中。
  • 使用接口回调:通过接口定义回调方法,避免直接依赖具体实现类。
  • 调整设计:重新审视业务逻辑,确保Bean之间的依赖是单向的。

示例重构:

// 1. 创建公共服务
class CommonService {public void sharedMethod() { /* ... */ }
}// 2. 让两个类依赖公共服务
class DataGenerationImpl {@Autowiredprivate CommonService commonService;// 移除对RegisterVersionSourceImpl的直接依赖
}class RegisterVersionSourceImpl {@Autowiredprivate CommonService commonService;// 移除对DataGenerationImpl的直接依赖
}
2. 使用Setter注入或构造器注入(结合@Lazy

如果确实无法避免循环依赖,可以使用以下方式:

Setter注入:

class DataGenerationImpl {private RegisterVersionSourceImpl registerVersionSource;@Autowiredpublic void setRegisterVersionSource(RegisterVersionSourceImpl registerVersionSource) {this.registerVersionSource = registerVersionSource;}
}class RegisterVersionSourceImpl {private DataGenerationImpl dataGeneration;@Autowiredpublic void setDataGeneration(DataGenerationImpl dataGeneration) {this.dataGeneration = dataGeneration;}
}

构造器注入+@Lazy

class DataGenerationImpl {private final RegisterVersionSourceImpl registerVersionSource;@Autowiredpublic DataGenerationImpl(@Lazy RegisterVersionSourceImpl registerVersionSource) {this.registerVersionSource = registerVersionSource;}
}class RegisterVersionSourceImpl {private final DataGenerationImpl dataGeneration;@Autowiredpublic RegisterVersionSourceImpl(@Lazy DataGenerationImpl dataGeneration) {this.dataGeneration = dataGeneration;}
}

@Lazy注解会告诉Spring在运行时才注入依赖,而不是在初始化时,从而打破循环。

3. 配置允许循环依赖(不推荐)

作为最后的手段,可以在application.propertiesapplication.yml中配置:

spring.main.allow-circular-references=true

但这种方法只是掩盖了问题,并没有真正解决依赖设计的缺陷,可能导致运行时问题。

总结

循环依赖通常是代码设计不合理的信号,优先通过重构消除依赖关系。只有在无法避免的情况下,才考虑使用@Lazy或配置允许循环依赖。良好的设计应该遵循单向依赖原则,使代码更清晰、可维护。

http://www.lqws.cn/news/139141.html

相关文章:

  • 还原Windows防火墙
  • 高效VLM:VisionZip
  • JavaWeb:前后端分离开发-登录认证
  • c++ 命名规则
  • LeetCode 2297. 跳跃游戏 VIII(中等)
  • Linux:理解库制作与原理
  • Python try-except-else 语句详解
  • AI赋能国风艺术:穿越时空的诗词画卷如何诞生?
  • 聊一聊接口测试的意义有哪些?
  • Unity与Excel表格交互热更方案
  • Vue全局事件总线
  • [Java 基础]创建人类这个类小练习
  • 代码随想录刷题day29
  • 微信小程序前端面经
  • 题山采玉:Day2
  • SCI论文核心框架与写作要素小结
  • Java - 数组
  • 高速ADC数据格式与JESD204B IP数据格式映射关系
  • Linux环境基础开发工具使用
  • 【工具使用】STM32CubeMX-FreeRTOS操作系统-任务、延时、定时器篇
  • Visual Studio 2022 在 Windows 11 添加资源时崩溃问题分析与解决方案
  • 数据结构与算法:动态规划中根据数据量猜解法
  • macOS 连接 Docker 运行 postgres,使用navicat添加并关联数据库
  • 【TCP/IP和OSI模型以及区别——理论汇总】
  • 实验设计如何拯救我的 CEI VSR 28G 设计
  • MySQL 8.0 窗口函数全面解析与实例
  • Day44 Python打卡训练营
  • 陈伟霆电视剧《九门》开机 续写传奇热血新篇
  • Apache APISIX
  • DeviceNET从站转EtherNET/IP主站在盐化工行业的创新应用