Spring循环依赖那些事儿(含Spring详细流程图)

如题所述

完整文章内容可点击下方链接查看:

本篇不仅介绍了Spring循环依赖的原理,还详细解析了Spring不能支持的循环依赖场景与案例,并给出了解决建议与方案,以减少未来的弯路。

作者 | 刘斌(蔆素)

来源 | 阿里开发者公众号

背景

1、循环依赖异常信息

2、依赖关系

3、涉及基础知识

问题

1、什么是循环依赖?

2、为什么会产生循环依赖?

3、循环依赖有哪些场景?

4、Spring如何解决循环依赖的?

5、Spring为什么使用三级缓存?

6、Spring支持AOP循环依赖,为何还存在循环依赖异常?

7、Spring不支持的循环依赖场景及如何解决?

注:Spring启动流程与Bean创建初始化流程如不熟悉,自行补习,篇幅原因此处不做介绍

Spring循环依赖

1、什么是循环依赖

2、核心概念

1、什么情况下出现循环依赖

2、循环依赖场景

3、三级缓存解决循环依赖

(1)、一级缓存

DefaultSingletonBeanRegistry

(2)、二级缓存

二级缓存(未初始化未填充属性提前暴露的Bean)

(3)、三级缓存

三级缓存(Bean创建时提供代理机会的Bean工厂缓存)

6、Spring为何不使用一级、二级缓存解决循环依赖

循环依赖产生在Bean创建时

三级缓存获取Bean

SmartInstantiationAwareBeanPostProcessor重点 -> APC之父

7、Spring支持动态代理循环依赖,为何还会出循环依赖异常?

(1)、相互依赖的Bean只有需要AOP或者动态代理时才有可能出现循环依赖异常

(2)、各别注解使用不当

(3)、存在多个AutoProxyCreator(APC),出现多层代理

spring默认保证一个容器中只能有一个Aop的APC,如过手动添加或者自定义会出现多个APC情况

AopConfigUtils

存在多个APC时,如存在循环依赖,此时触发之前放入三级缓存逻辑

从而触发多个APC的 getEarlyBeanReference

最终proxy2会被注入到依赖的Bean中,即例如:A-proxy2 注入到 B中存在多个多层代理情况,getEarlyBeanReference 没有问题,但是执行到初始化时

8、正常AOP代理为何没问

SmartInstantiationAwareBeanPostProcessor

解决方案

1、无需代理场景使用原始对象

2、@lazy解耦

DefaultListableBeanFactory#resolveDependency

3、抽取公共逻辑

案例(可直接运行)

1、@Repository案例分析

2、多AutoProxyCreator场景

总结

出现循环依赖其实反映代码结构设计上的问题,理论上应当将循环依赖进行分层,抽取公共部分,然后由各个功能类再去依赖公共部分。

但是在复杂代码中,各个service、manager类互相调用太多,总会一不小心出现一些类之间的循环依赖的问题。可有时候我们又发现在用Spring进行依赖注入时,虽然Bean之间有循环依赖,但是代码本身却大概率能很正常的work,似乎也没有任何bug。

很多敏感的同学心里肯定有些犯嘀咕,循环依赖这种触犯因果律的事情怎么能发生呢?没错,这一切其实都并不是那么理所当然。Spring已经为我们背负了太多,但绝不是偷懒的借口,还是应该规范设计,规范代码,尽量做到从根本上避免这种循环依赖的发生。

阿里云开发者社区,千万开发者的选择。百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,尽在:
温馨提示:答案为网友推荐,仅供参考
相似回答
大家正在搜