Spring 加载过程之循环依赖问题学习笔记

Spring 加载过程学习
启动:AbstractApplicationContext

obtainFreshBeanFactory这里插入图片描述
obtainFreshBeanFactory():加载bean信息。主要是通过DefaultListableBeanFactory来加载。

在这里插入图片xml描述
obtainFreshBeanFactory()里面通过loadBeanDefinitions()加载bean信息时,这里多个子类分别对应xml和注解扫描.然后组装成BeanDefintion放到BeanFactory里。

finishBeanFactoryInitialization():进行bean的实例化,创建单例,解析@Autowiered注解等。
其中实例化时getSingleton()这里就是设置三级缓存,并获取bean(这就是Spring允许循环依赖的原因)。最后放进beanFactroy.

三级缓存获取过程:(singletonObjects,earlySingletonObjects,singletonFactories)
1.判断一级是否存在,一级缓存里bean为空并且bean在正在创建过程中才会从二级缓存中获取。否则返回空。如果从二级缓存获取还是空,则从三级缓存里获取,并把它放入二级缓存。然后在从三级缓存里移除。
2.判断从三级缓存里都取不到bean A,开始A的实例化,实例化完成后加入第三级缓存(singletonFactories放的是实例化的这个类。)实例化后开始初始化(处理A类属性,比如A类依赖B类),从bean工产里面获取类b,此时b的类还没有创建的话,则需要创建这个类,重复上面流程,把B也放入第三级缓存singletonFactories。此时A和B都被实例化,但是都还没有初始化。
3.如果B也依赖A,那么在B实例化时,重复上面流程,B的初始化首先从一级里面取A,没有,但是A正在创建过程中,所以此时从二级里面取,二级里面没有。所以从三级里面取到A,然后并把A放入二级缓存。然后在从三级缓存里移除A.
4.此时B完成了初始化,把b放入一级缓存,a还在初始化过程。然后重复上面流程。此时B已存在,所以A可以初始化完成。同样把a放入一级,然后再从二级里移除。

从上面流程可以看出,解决循环依赖的关键是实例化和初始化分开的(实例化时就就放入三级缓存。)。如果A里面把B定义成静态的,那么A在实例化时就必须获取到B,而此时B还没创建,创建B的时候又依赖A,然而A还在实例化,三级缓存里面还没有A,所以b初始化失败,报找不到A类。

为什么使用三级缓存呢?
1.只有一级缓存的话,里面会存在很多实例化但未初始化的数据,多线程环境下都从一级缓存取,这样会导致很多依赖数据为空。
2.二级缓存可以解决循环依赖问题,三级缓存的意义?
解决代理类的问题。如果只有二级(一级二级里面放的都是object,三级放的是FactoryObject),刚开始二级放的是实例好的对象,那么代理处理生成新的代理类的时候,重新放入二级。那么之前和之后,别人取到的类就不是同一个了。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值