Spring如何解决循环依赖


	Spring如何解决循环依赖
[编程语言教程]

1,什么是循环依赖

简单的说就是A依赖B,B依赖C,C依赖A这样就构成了循环依赖。

技术图片

 

 

循环依赖分为构造器依赖和属性依赖,众所周知的是Spring能够解决属性的环依赖(set注入)。下文将从源码角度分析Spring是如何解决属性的循环依赖。

2,思路

如何解决循环依赖,Spring主要的思路就是依据三级缓存,在实例化A时调用doGetBean,发现A依赖的B的实例,此时调用doGetBean去实例B,实例化的B的时候发现又依赖A,如果不解决这个循环依赖的话此时的doGetBean将会无限循环下去,导致内存溢出,程序奔溃。spring引用了一个早期对象,并且把这个”早期引用”并将其注入到容器中,让B先完成实例化,此时A就获取B的引用,完成实例化。

 

3,三级缓存

Spring能够轻松的解决属性的循环依赖正式用到了三级缓存,在AbstractBeanFactory中有详细的注释。

一级缓存:singletonObjects,存放完全实例化属性赋值完成的Bean,直接可以使用。

二级缓存:earlySingletonObjects,存放早期Bean的引用,尚未属性装配的Bean三级缓存:singletonFactories,

三级缓存,存放实例化完成的Bean工厂。

 

什么是循环依赖

简单的说就是A依赖B,B依赖C,C依赖A这样就构成了循环依赖。

开撸

先上一张流程图看看Spring是如何解决循环依赖的

技术图片

 

 

上图标记蓝色的部分都是涉及到三级缓存的操作,下面我们一个一个方法解析

【1】 getSingleton(beanName):源码如下:

技术图片

 

 从源码可以得知,doGetBean最初是查询缓存,一二三级缓存全部查询,如果三级缓存存在则将Bean早期引用存放在二级缓存中并移除三级缓存。(升级为二级缓存)

【2】addSingletonFactory:源码如下

技术图片

 

 从源码得知,Bean在实例化完成之后会直接将未装配的Bean工厂存放在三级缓存中,并且移除二级缓存

【3】addSingleton:源码如下:

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » Spring如何解决循环依赖