网站首页 > 博客文章 正文
在 Spring Boot 的世界里,循环依赖问题一直是开发者们需要谨慎处理的一个话题。从 Spring Boot 2.6.0 开始,官方默认禁用了循环依赖,一旦在应用中存在循环依赖关系,启动时会直接报错。这引起了不少开发者的关注和讨论。那么,什么是循环依赖?默认禁用循环依赖后,我们该如何应对?今天,我们一起深入探讨这些问题。
什么是循环依赖?
循环依赖是指在 Spring IoC 容器中,两个或多个 Bean 之间相互依赖,形成一个闭环。例如,Bean A 依赖于 Bean B,同时 Bean B 依赖于 Bean A。这样的依赖关系如果没有适当的处理,可能会导致应用启动失败或运行时错误。
Spring 中的缓存机制
在 Spring 中,为了管理 Bean 的依赖关系,使用了三级缓存机制来解决循环依赖问题。
- 一级缓存(Singleton Objects):用于存放完全初始化好的单例 Bean。
- 二级缓存(Early Singleton Objects):用于存放提前曝光的单例 Bean,解决正在创建中但尚未完全初始化的 Bean 的依赖问题。
- 三级缓存(Singleton Factories):用于存放 Bean 工厂,通过其获取 Bean 的代理对象,支持 AOP 等功能。
详细的循环依赖处理可以参考“一文彻底明白 Spring 的循环依赖”的第四五六节内容。
Spring Boot 2.6.0 起循环依赖默认禁用 ?
从 Spring Boot 2.6.0 开始,循环依赖默认被禁用。如果存在循环依赖关系,应用启动时将报错:
BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
如何应对循环依赖???
解决方案1:重新设计依赖关系
最佳实践是避免循环依赖,重新设计 Bean 之间的依赖关系,确保不存在循环引用。这是最根本的解决之道。
// 修改前
@Component
public class BeanA {
@Autowired
private BeanB beanB;
}
@Component
public class BeanB {
@Autowired
private BeanA beanA;
}
// 修改后
@Component
public class BeanA {
private final BeanB beanB;
@Autowired
public BeanA(BeanB beanB) {
this.beanB = beanB;
}
}
@Component
public class BeanB {
private final BeanA beanA;
@Autowired
public BeanB(@Lazy BeanA beanA) {
this.beanA = beanA;
}
}
通过使用 @Lazy 延迟初始化,可以打破循环依赖。
解决方案2:启用循环依赖支持(不推荐)
如果确实无法避免循环依赖关系,可以选择启用循环依赖支持(仅建议在特殊情况下使用)。
在 application.properties 中添加以下配置:
spring.main.allow-circular-references=true
代码示例与解析
以下是一个完整代码示例,展示如何处理 Spring Boot 2.6.0 默认禁用循环依赖的情况。
示例1:重新设计依赖关系
修改前:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanA {
@Autowired
private BeanB beanB;
}
@Component
public class BeanB {
@Autowired
private BeanA beanA;
}
修改后:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class BeanA {
private final BeanB beanB;
@Autowired
public BeanA(BeanB beanB) {
this.beanB = beanB;
}
}
@Component
public class BeanB {
private final BeanA beanA;
@Autowired
public BeanB(@Lazy BeanA beanA) {
this.beanA = beanA;
}
}
示例2:启用循环依赖支持
application.properties:
spring.main.allow-circular-references=true
源码解析
- 在 Spring Boot 2.6.0 以前,Spring 通过三级缓存机制解决循环依赖问题。
- 三级缓存机制中,一级缓存存放完全初始化好的 Bean,二级缓存存放提前曝光的 Bean,三级缓存存放 Bean 工厂。
- 从 Spring Boot 2.6.0 起,默认禁用了循环依赖,旨在鼓励开发者通过合理设计避免循环依赖问题。
总结
Spring Boot 2.6.0 禁用循环依赖的变更是为了提升应用的健壮性和代码质量。通过重新设计依赖关系或在特殊情况下启用循环依赖支持,我们可以有效地应对这一变更。掌握这些知识和技巧,让你的 Spring Boot 项目更加稳定和高效!
不断学习,拥抱变化,让代码更优秀!
坚持学习,每天进步一点点!
分享知识,共同成长!祝你开发顺利!
猜你喜欢
- 2024-12-14 不服不行啊!大牛确实把SpringCloud集成Dubbo给一次性讲透了
- 2024-12-14 SpringBoot + minio + kkfile 实现文件预览
- 2024-12-14 基于Spring Boot 2.2.6实现Rest风格的文件上传&下载APIs-附源码
- 2024-12-14 如何通过SpringBoot 实现一个OAuth2.0的提供者?
- 2024-12-14 springboot2.2.X手册:5分钟用Netty搭建高性能异步WebSocket服务
- 2024-12-14 Spring Boot 3.0 要来了,这个特性真心强
- 2024-12-14 妹子始终没搞懂OAuth2.0,今天整合Spring Cloud Security 说明白
- 2024-12-14 SpringBoot 3.2:CRaC技术助力启动速度飞跃
- 2024-12-14 拿捏SpringBoot自动配置实战演示
- 2024-12-14 SpringBoot 3.3.5 试用CRaC,启动速度提升3到10倍
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)