一文搞懂 Spring 循环依赖
创作时间:
作者:
@小白创作中心
一文搞懂 Spring 循环依赖
引用
CSDN
1.
https://blog.csdn.net/u012702547/article/details/139497162
Spring框架中的循环依赖是一个常见的面试话题,也是一个容易引发系统错误的技术难点。本文将深入探讨Spring如何处理循环依赖,以及在特定场景下循环依赖的解决方案。
一、循环依赖
1.1 什么是循环依赖
循环依赖指的是两个或多个Bean互相依赖的情况。例如:
@Service
public class AService {
@Autowired
BService bService;
}
@Service
public class BService {
@Autowired
AService aService;
}
这种依赖关系可以表示为:
1.2 循环依赖的类型
循环依赖主要有三种形态:
- 两个Bean互相依赖(如上例)
- 三个或更多Bean形成依赖环
- Bean自我依赖
一般来说,如果代码中出现循环依赖,说明设计上可能存在问题。虽然Spring默认可以处理循环依赖,但这种代码结构并不推荐。
二、循环依赖解决思路
2.1 解决思路
Spring通过引入三级缓存机制来解决循环依赖问题:
- earlySingletonObjects(二级缓存):存储通过反射创建但尚未完成初始化的Bean实例。
- singletonObjects(一级缓存):存储已完成初始化的Bean实例。
- singletonFactories(三级缓存):存储创建Bean实例的工厂对象,用于处理AOP代理。
具体流程如下:
- 创建AService实例时,先通过反射创建一个原始的AService对象,并存入二级缓存。
- 在给AService设置属性时,发现需要BService,于是创建BService。
- 创建BService时发现需要AService,从二级缓存中获取AService的原始对象使用。
- BService创建完成后,将其赋值给AService,此时AService和BService都创建完成。
2.2 存在AOP怎么办
当涉及AOP时,情况会更复杂。Spring通过三级缓存机制提前处理AOP,确保依赖关系正确:
- 在创建Bean时,如果需要AOP代理,先在三级缓存中保存一个生成代理对象的工厂。
- 在处理循环依赖时,从三级缓存中获取工厂生成代理对象,而不是直接使用原始Bean。
- 最终确保所有依赖都指向正确的代理对象。
2.3 小结
Spring解决循环依赖的关键在于:
- 提前暴露:将未完成初始化的Bean提前暴露给其他Bean使用。
- 提前AOP:在处理循环依赖时提前处理AOP代理。
三、特殊情况
3.1 基于构造器注入
如果依赖是通过构造器注入的,Spring无法解决循环依赖,因为创建Bean时就需要完整的依赖对象。例如:
@Service
public class AService {
BService bService;
public AService(BService bService) {
this.bService = bService;
}
}
@Service
public class BService {
AService aService;
public BService(AService aService) {
this.aService = aService;
}
}
3.2 prototype对象
当循环依赖的Bean作用域为prototype时,也会导致循环依赖失败,因为每次都需要现场创建Bean。
3.3 @Async
带有@Async注解的Bean产生循环依赖时,由于AOP处理的特殊性,Spring也无法自动解决。
四、@Lazy注解解决方案
通过添加@Lazy注解,可以解决上述三种特殊场景的循环依赖问题。@Lazy注解的工作原理是为依赖对象生成一个代理对象,延迟实际对象的加载。
例如:
@Service
public class AService {
@Autowired
@Lazy
BService bService;
@Async
public void hello() {
bService.hello();
}
}
原理分析
@Lazy注解的处理主要发生在属性注入过程中:
- 在
resolveFieldValue
方法中,调用resolveDependency
方法解析依赖。 - 在
resolveDependency
方法中,检查是否需要延迟加载(通过getLazyResolutionProxyIfNecessary
方法)。 - 如果需要延迟加载,构建一个代理对象(通过
buildLazyResolutionProxy
方法)。
代理对象在需要时才会真正加载依赖Bean,从而避免了循环依赖问题。
总结
虽然Spring提供了多种机制来处理循环依赖,但在实际开发中,还是应该尽量避免循环依赖的出现,通过合理的模块划分和设计模式来优化代码结构。
本文内容参考自CSDN,原文链接:https://blog.csdn.net/u012702547/article/details/139497162
热门推荐
如何有效测试DNS解析速度?
给狗狗吃益生菌的好处与喂养频率(减少疾病发生的关键,每周喂食益生菌)
初次填报加拿大个人所得税?下文介绍了您应该注意的几件事。
“人心中的成见就像一座大山”,《哪吒2》石矶娘娘:那很漂亮啦!
《晚熟的人》:人生的底气不是财富,不是地位,更不是人脉,而是拥有这3种能力
“大黄”记情
社融是什么意思?社融数据对经济的指示作用是什么?
补充能量最好的方式:天补、自补、人补
HRBP培训课程有哪些内容?
如何给企业合理估值?巴菲特通过这两招“轻松”搞定!
被后车追尾怎么合理处理?处理后怎么检查车辆损伤情况?
深海鱼油能否改善心血管健康?一文带你了解!
这一站,济南!双节临近,探寻老舍笔下的诗意泉城
牙隐裂是什么?属于:不全牙裂或牙微裂,看看检查方法与治疗方案吧!
20种助眠卧室植物推荐,改善失眠、浅眠并提升睡眠品质
瘦人血压高是怎么回事
《最后一课》没有骗你:阿尔萨斯-洛林人为何更认同法国
深度学习项目的预算和成本如何控制?
超级大回暖持续!下周南宁将“断崖式”降温……
最新研究:睡眠不规律会增加糖尿病风险,即使睡眠时长达标也不例外
紫苏什么季节种植比较好?附58种易种中药材推荐
快克的副作用有哪些
如何判断主力在股票中的动向?这种判断方法的准确性如何?
刑事拘留期间可以取保候审吗
北京画院年会:学者共话“齐白石何以成为大师”
重庆城市更新经验走向全国!这3个案例被住建部推荐
大数据分析:处理海量数据的方法和技巧
从基础到巅峰:2025考研数学复习指南
《三国志战略版》兵种克制关系介绍
地震的时空分布规律 地震的时空分布特征