spring的bean生命周期之循环依赖的全过程

it2026-01-01  1

更新了流程图:https://blog.csdn.net/weixin_43795033/article/details/110135625 还挺详细的,可以结合流程图看这篇文章。

说明:因为贴代码会让文章变的繁杂,为了更连续的说明,只贴上必须的代码段以及重要的逻辑顺序,可以根据下面的入口方法看着笔记去了解这个过程;

AbstractBeanFactory{ public Object getBean(String name) throws BeansException { return this.doGetBean(name, (Class)null, (Object[])null, false); } } ---------------------------------------------正文开始昂!----------------------------------------------- @Component | @Component public class X{ | public class Y{ @Autowire | @Autowire private Y y; | private X x; } | } 需要提前知道的东西: singletonObjects、earlySingletonObjects、singletonFactories--------这三个就是常说的三级缓存; 注意singletonObject和bean的区别: Object singletonObjects=singletonObjects.get(String beanName) bean=getObjectForBeanInstance(Object beanInstance,String name,String beanName,RootBeanDefinition mbd); spring启动,调用链为refresh方法-->finishBeanFactoryInitialization方法-->beanFactory.preInstantiateSingletons() beanFactory.preInstantiateSingletons()中根据遍历beanDefinitionNames去调用getBean(String beanName)方法; getBean-->doGetBean(); 假设先扫描到了组件X: doGetBean方法调用顺序:getSingleton(String beanName)--->getSingleton(beanName,true);

------------------------这部分为getSingleton(beanName,true)的介绍,可以跳过--------------------------

protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) { synchronized(this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } }   return singletonObject; }

方法首先调用Object singletonObject=this.singletonObjects.get(String beanName),

如果singletonObject为null并且"当前bean正在被创建"时

--------->调用singletonObject=this.earlySingletonObjects.get(String beanName),

如果singletonObject为null并且允许提前引用时

--------->调用调用ObjectFactory<?> singletonFactory=this.singletonFactories.get(String beanName),

如果singletonFactory!=null时

--------->调用singletonObject=singletonFactory.getObject(); getObject()是一个函数式接口,

里面会调用doCreateBean() 、this.earlySingletonObjects.put(String beanName,Object singletonObject)

、this.singletonFactories.remove(String beanName)

最后--------->return singletonObject 此次是第一次调用getSingleton方法,"当前bean没有正在创建",

所在getSingleton的第一步 Object singletonObject=this.singletonObjects.get(String beanName)时

就返回一个为null的singletonObject; 

----------------------------------------------------------------------------------------------------------------------------------------------------------

 接下来会合并当前beanDefinition对象(具体内容不做介绍),接下来判断该beanDefinition是否是单例的,如果是则spring会调用方法:

if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }

--此部分是getSingleton(String beanName,ObjectFactory<?> singletonFactory)方法执行逻辑介绍,很重要-- 

getSingleton(String beanName,ObjectFactory<?> singletonFactory 其中ObjectFactory<?>是一个函数式接口,

里面只有一个getObject方法; getSingleton(String beanName,ObjectFactory<?> singletonFactory)进入后首先:

Object singletonObject=this.singletonObjects.get(beanName); 此时因为是第一次调用,所以singletonObject

为null,当singletonObject为null时会进入一个if断码段; 该代码段首先会执行beforeSingletonCreation(),

该方法会将此beanName标志成"正在创建中"; 然后调用singletonFactory.getObject()方法,也就是前面传入的

函数式接口方法,即最终调用到传入的createBean()方法;

------------------------------------------------------------------------------------------------------

----------------------------------此部分是crateBean方法介绍,很重要----------------------------------

crateBean调用到doCreateBean,在doCreateBean中首先final Object bean=instanceWrapper.getWrapperInstance();

然后判断判断当前beanDefinition是否是单例且是允许提前暴露引用且是正在被创建,如果条件满足则会调用

addSingletonFactory(beanName,()->getEarlyBeanReference(beanName,beanDefinition,bean))

(这一步很重要,文章末尾有彩蛋)方法,该方法内容如下: 

addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){ Assert.notNull(singletonFactory,"Singleton factory must not be null"); synchronized(this.singletonObjects){ if(!this.singletonObjects.containKey(beanName)){ this.singletonFactories.put(beanName,singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } } 继而调用populateBean(beanName,beanDefinition,instanceWrapper),此方法就是实现了bean的自动注入的方法; 当X的bean实例化过程中调用到了populateBean后,因为X依赖Y,所以在populateBean内部会调用getBean("y"); 相同的,Y从getBean(beanName)开始,和上面经过一模一样的步骤,然后走到了populateBean方法,然后又以为Y依赖X,所以又会调用getBean("x"); 此时此刻的getBean("x")就和第一次执行getBean("X")不一样了; getBean(beanName)-->doGetBean(): doGetBean首先调用的代码:Object sharedInstance=getSingleton(beanName); 这个时候的getSingleton(beanName)因为单例池中没有x,而且x是正在被创建,又因为earlySingletonObjects中没有x,x又允许提前暴露, 所以代码最终会到: ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } 因为x调用doCreateBean的时候调用了addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory)所以这个时候的 singletonFactory不为null,即代码会调用到singletonFactory.getObject(),这个getObject()方法即为getEarlyBeanReference(beanName,beanDefinition,bean)方法; 然后拿到了singletonObject并将其放入earlySingletonObjects中,并将singletonFactories中的工厂对象删除,见如上代码; 执行完后,sharedInstance不为null,则不会在调用x的创建逻辑,而是直接返回所需要的bean对象,返回后Y的populateBean方法也会正常退出, Y执行完populateBean后再执行一系列操作,然后将此对象put到单例池中,此时Y注入了earlySingletonObjects中的X; 也就是getEarlyBeanReference(beanName,beanDefinition,bean)得到的对象,也即X创建过程中执行populateBean方法前创建的那个对象instanceWrapper经过 SmartInstantiationAwareBeanPostProcessor处理之后的对象(这部分会在下面的彩蛋里说明); 当Y创建完成后,执行逻辑回到最开始X的populateBean,此时X也可以成功注入Y了,执行完populateBean之后,X也被put到单例池,即循环引用的bean创建完成;

----------------------------------------------------------------------------------------------------

这里抛出一个问题:为什么要用三级缓存,两级缓存不行吗?取消singletonFactories,直接把提前暴露的bean放在earlySingletonObjects里不更方便吗?

解答一下这个问题,重点就在上面提到的这个方法: 

addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){ Assert.notNull(singletonFactory,"Singleton factory must not be null"); synchronized(this.singletonObjects){ if(!this.singletonObjects.containKey(beanName)){ this.singletonFactories.put(beanName,singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }  

这一步将一个ObjectFactory<?>对象放了进去,前面也提及了,他是一个函数式接口(实现lambda表达式的);

而doCreateBean方法掉用这个函数的代码为addSingletonFactory(

beanName,()->getEarlyBeanReference(beanName,beanDefinition,bean)

);

上文提到populateBean方法执行完之后会执行getSingleton(String beanName,boolean allowEarlyReference),

在这个方法里会调用addSingletonFactory方法 里传入的

getEarlyBeanReference(beanName,beanDefinition,bean)方法,我们看下这个方法:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }

 

看到这里一切都很明了了,这个方法会调用一个叫做SmartInstantiationAwareBeanPostProcessor的

BeanPostProcessor, 这个BeanPostProcessor里有个叫getEarlyBeanReference的方法,这个方法可以

被开发人员实现并进行一些自定义操作;想必大家到这里也明白了,spring为什么设计三级缓存,

就是因为为了让开发人员实现这个接口做sprig的拓展,比如实现aop、执行自定义的beanPostPrcessor

等一些操作(开闭原则)。 

最新回复(0)