错误再现
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-06-17 16:52:41.008 ERROR 20544 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: The dependencies of some of the beans in the application context form a cycle: ┌─────┐ | redisAutoInit (field protected com.alicp.jetcache.anno.support.ConfigProvider com.alicp.jetcache.autoconfigure.AbstractCacheAutoInit.configProvider) ↑ ↓ | springConfigProvider └─────┘ Action: Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
简介
当应用程序上下文中的一些bean的依赖关系形成循环时,意味着这些bean之间存在循环依赖关系。换句话说,Bean A依赖于Bean B,同时Bean B又依赖于Bean A,形成一个闭环。这种情况通常发生在使用依赖注入框架(如Spring)管理bean之间的依赖关系时。
典型的循环依赖问题
循环依赖可能导致以下问题:
- 初始化问题:如果两个或多个bean彼此依赖,框架可能无法解析哪个bean应该先初始化,从而导致初始化失败或延迟。
- 运行时异常:常见的错误是
BeanCurrentlyInCreationException
,它表明Spring在尝试创建bean实例时检测到循环依赖。 - 代码的可维护性降低:循环依赖增加了组件之间的耦合性,使代码更难理解和维护。这可能使代码变得更脆弱,难以修改或测试。
如何处理循环依赖
在Spring中,有几种处理循环依赖的方法:
- 构造函数注入:首选使用构造函数注入而不是setter方法注入。构造函数注入有助于打破循环,因为所有依赖关系在bean实例化时都会被解析。
- 延迟注入:使用
@Lazy
注解延迟注入依赖关系。这可以推迟直到需要时才注入bean,从而可能打破循环。 - 方法注入:在某些情况下,可以使用方法注入并在方法上使用
@Autowired
注解。这种方法也可以帮助打破循环依赖。 - Aware接口:对于无法通过直接依赖注入解决的情况,可以考虑使用
Aware
接口,如ApplicationContextAware
或BeanFactoryAware
。 - 使用代理解决:在某些情况下,Spring可以通过运行时代理来管理循环依赖。
最佳实践
- 避免循环依赖:尽量避免设计中出现循环依赖。循环依赖通常表明设计可能需要重新审视,以增强模块化和降低耦合度。
- 使用构造函数注入:构造函数注入通常是处理循环依赖的最佳实践,因为它使依赖关系更明确,并且有助于避免初始化顺序问题。
- 进行代码审查和测试:对可能存在循环依赖的代码进行彻底的代码审查和测试,以尽早发现并解决问题。
处理循环依赖需要综合考虑应用程序的架构和设计。Spring提供了多种机制来处理这些情况,但理想情况下,应该尽量设计具有清晰依赖关系且避免循环依赖的代码结构。
两种解决方案
解决方案一
降低spingboot的版本
在pom.XML文件中去修改
<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.6.13</spring-boot.version> </properties>
解决方案二
在yml配置文件里配置属性
配置spring框架的属性
spring: datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC username: root password: 123456 devtools: restart: # 设置不参与热部署的文件或文件夹 exclude: static/**,public/**,config/application.yml main: allow-circular-references: true
主要是这一行
这段配置看起来像是针对某种配置文件或框架的设置,其中 allow-circular-references: true
的意思是允许循环依赖。
在某些依赖注入框架(比如Spring)中,默认情况下是不允许循环依赖的,因为循环依赖可能导致初始化顺序问题或者在解析依赖关系时产生死锁。但有时候,循环依赖是不可避免的或者设计上是合理的,因此框架允许用户显式地设置来解决这类问题。
解释:
- allow-circular-references: true:这个配置告诉框架或配置文件,允许在应用程序上下文中出现循环依赖。这意味着,如果两个或多个bean彼此依赖,并且形成了循环依赖,框架会尝试解决这些依赖关系而不会报错。
注意事项:
- 慎重使用:虽然允许循环依赖可以解决特定情况下的问题,但过度依赖循环依赖可能导致代码难以理解和维护。
- 替代解决方案:通常情况下,尝试避免设计上需要循环依赖的情况是更好的选择。可以考虑通过重构或者重新设计来减少循环依赖的发生。
- 框架特定性:具体实现可能会有所不同,需要查阅相应框架的文档以了解详细的配置方法和影响。
总之,这种配置通常用于在特定场景下解决循环依赖问题,但使用时需要谨慎考虑其长期维护和代码质量的影响。
main: allow-circular-references: true
成功启动