假设:A依赖B,B依赖A,A,B相互依赖.

大体流程如下图所示:

首先A先执行getBean(),getBean里面调用doGetBean方法,doGetBean再调用getSingleton(beanName)从缓存中获取实例,进入方法里面,先从一级缓存里面拿,一级缓存里面没有,再从二级缓存,二级缓存没有再从三级缓存里拿,刚开始BeanA进来,1,2,3级缓存都是没有的。getSingleton(beanName)返回null.

 缓存里面都没有,调用createBean创建实例。

 进入createBean中调用doCreateBean,进入里面调用createBeanInstance(beanName, mbd, args)创建bean对象,并将bean对象包裹在BeanWrapper对象中,调用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))把实例出来的beanA放入三级缓存中。

放入三级缓存后,然后填充属性,初始化给定的bean实例,应用工厂回调以及init方法和bean后处理器。但在调用populateBean(beanName, mbd, instanceWrapper)填充属性时,发现beanA有一个属性是B的对象。

 进入populateBean(beanName, mbd, instanceWrapper),依次再进入applyPropertyValues(beanName, mbd, bw, pvs),valueResolver.resolveValueIfNecessary(pv, originalValue),resolveReference(argName, ref)方法。执行到bean = this.beanFactory.getBean(refName)这行,执行getBean方法,再次调用doGetBean方法创建B的实例,依次执行doGetBean、查询缓存(getSingleton)、createBean创建实例,执行populateBean装配属性,发现有一个属性是A对象,因此再次调用doGetBean创建A的实例,但是执行到getSingleton查询缓存的时候,从三级缓存中查询到了A的实例(早期引用,未完成属性装配),把A放到二级缓存中,此时直接返回A,不用执行后续的流程创建A了,那么B就完成了属性装配,然后B执行init方法和bean后处理器完成初始化。

 

 然后将beanB返回,将beanB设置到一级缓存中。

 

 这个时候我们在回到A的填充属性方法populateBean(beanName, mbd, instanceWrapper)中。A依赖的bean B已经初始化好了,然后已经放到一级缓存中了。当A填充属性的时候,直接从一级缓存中换取B,然后填充进来,执行执行init方法和bean后处理器完成初始化.

 最后把A也返回,并将A设值到一级缓存中。

 最后return (T) bean。

 

posted on 2021-02-05 14:29  路飞_lufei  阅读(69)  评论(0编辑  收藏  举报