彻底理解Spring如何解决循环依赖

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了彻底理解Spring如何解决循环依赖相关的知识,希望对你有一定的参考价值。

参考技术A

可以简化为以下5步。

1、构建BeanDefinition

2、实例化 Instantiation

3、属性赋值 Populate

4、初始化 Initialization(BeanPostprocessor -> Aware,init)

5、销毁 Destruction

用来保存实例化、初始化都完成的bean对象。

用来保存实例化完成,但是未初始化完成的对象(这个对象不一定是原始对象,也有可能是经过AOP生成的代理对象)。

用来保存一个对象工厂(ObjectFactory),提供一个匿名内部类,用于创建二级缓存中的对象。

三级缓存中提到的ObjectFactory即 () -> getEarlyBeanReference(beanName,mbd,bean),其中bean就是原始对象。

其中 getEarlyBeanReference 方法是 SmartInstantiationAwareBeanPostProcessor接口中定义的,AbstractAutoProxyCreator(Spring AOP proxy creator)实现了该方法。

分别按照一级缓存、二级缓存、三级缓存顺序加载。如果存在循环依赖(比如beanName:B依赖beanName:A),而且三级缓存中存在beanName:A的引用,则从三级缓存中拿到beanName:A对应的提早曝光的对象(可能是原始对象,也可能是代理对象)并放入二级缓存。比如又有beanName:C依赖beanName:A,会直接从二级缓存中获取到。

直接添加到一级缓存

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(beanName:A, allowEarlyReference:false)

@Transactional使用的是自动代理创建器AbstractAutoProxyCreator,它实现了getEarlyBeanReference()方法从而很好的对循环依赖提供了支持。

@Async的代理创建使用的是AsyncAnnotationBeanPostProcessor单独的后置处理器实现的,它只在一处postProcessAfterInitialization()实现了对代理对象的创建,因此若出现它被循环依赖了,就会报BeanCurrentlyInCreationException。

具体原因分析参考: https://blog.csdn.net/f641385712/article/details/92797058

1、Spring 解决循环依赖有两个前提条件:不全是构造器方式的循环依赖,必须是单例。

2、如果没有出现循环依赖,第三级缓存(singletonFactories)将不会使用到,对象会按照Spring创建bean的生命周期流程,最后将bean直接放到第一级缓存(singletonObjects)中。

3、一定要三级缓存嘛,二级缓存不能解决循环依赖?不能,主要是为了生成代理对象。

因为三级缓存中放的是生成具体对象的匿名内部类(ObjectFactory),它可能生成代理对象,也可能是普通的实例对象。使用三级缓存主要是为了保证不管什么时候使用的都是一个对象。假设只有二级缓存的情况,往二级缓存中放的显示一个普通的Bean对象, BeanPostProcessor 去生成代理对象之后,覆盖掉二级缓存中的普通Bean对象,无法保证程多线程环境下获取到bean对象一致性。

硬核!一张图彻底搞懂Spring循环依赖!!(建议收藏)

大家好,我是冰河~~

最近,在看Spring源码,看到Spring解决循环依赖问题的源码时,不得不说,源码写的太烂了。像Spring这种顶级的项目源码,竟然存在着这种xxx的代码。看了几次都有点头大,相信很多小伙伴都会跟我有一样的感受。怎么办呢?还是踏下心来,慢慢啃源码。最终,我将Spring如何解决循环依赖的源码总结成下面的流程图,这样,根据流程图读源码就清晰多了!!

图解Spring循环依赖

Spring解决循环依赖问题的源码写的确实挺烂的,就是一顿 if + else 的嵌套操作。暂时还是不给小伙伴们上源码了。我将Spring解决循环依赖问题的源码总结成下面的流程图,看起来就清晰多了,结合流程图看Spring源码,事半功倍。

不多说了,上图:

在这里插入图片描述

说句实在话,看Spring源码,总结,画图。输出上面这张图就花了我将近3个小时。小伙们结合这张图看Spring源码吧,相信一定不会让你失望。如果对你有帮助的话,请点个赞、收藏、评论,分享吧。

写在最后

如果你想进大厂,想升职加薪,或者对自己现有的工作比较迷茫,都可以私信我交流,希望我的一些经历能够帮助到大家~~

推荐阅读:

好了,今天就到这儿吧,小伙伴们点赞、收藏、评论,一键三连走起呀,我是冰河,我们下期见~~

以上是关于彻底理解Spring如何解决循环依赖的主要内容,如果未能解决你的问题,请参考以下文章

Spring:bean的循环依赖问题

硬核!一张图彻底搞懂Spring循环依赖!!(建议收藏)

画图带你彻底弄懂三级缓存和循环依赖的问题

Spring是如何解决循环依赖的?

面试题:如何解决Spring 的循环依赖问题

spring如何解决循环依赖