spring源码系列 bean的生命周期

本文使用的spring版本是5.3.13

这一节我从源码的角度来简单分析下spring bean的生命周期,首先有几个前置知识:

(1) ApplicationContext类型容器的内部持有一个BeanFactory类型的容器,所有的bean实际是存放在这个内置容器中的。

(2) ApplicationContext类型的容器在启动的过程中会自动创建所有单例类型的bean,容器内部创建bean的时候实际是调用了AbstractBeanFactory#getBean(java.lang.String beanName)这个方法,该方法的内部会先根据bean名称获取bean,如果获取不到就会去创建bean

结合上边两点可以了解到研究bean的生命周期实际上就是看这个方法的执行逻辑。

一 、起点: AbstractBeanFactory#getBean(java.lang.String)

这个方法中只是调用了下自己的另一个方法 doGetBean

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

所以重点在这个doGetBean中

二、AbstractBeanFactory#doGetBean

从这个doGetBean方法开始才是真正的获取bean的逻辑,这个方法中先依次从spring的三级缓存中去获取bean,

如果获取到了就会返回,获取不到才会去走创建逻辑。

2.1 依次从三级缓存中获取bean

这里简单贴下获取的代码

这个getSingleton就是在从三级缓存中获取

这是获取的详细逻辑,分别从三级缓存中获取,其中

singletonObjects 一级缓存,就是常说的单例池,用来存储完整的bean

earlySingletonObjects 二级缓存,用来存储未创建完成的bean

singletonFactories 三级缓存,里边存的是一个ObjectFactory,执行getObject才会返回一个对象

这个后边再仔细看,现在只需要对三级缓存有一个了解就行。

2.2 创建bean

创建bean在从缓存中没有获取到bean时执行

就是这个createBean方法,在这里边是创建bean的逻辑。当然这段代码还是在AbstractBeanFactory#doGetBean里边。

2.3 createBean方法详解

这个createBean方法在AbstractBeanFactory中是一个抽象方法,在AbstractAutowireCapableBeanFactory中进行了实现。

AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

这个方法中主要做了这几件和生命周期有关的事情:

2.3.1 实例化前

(1) 执行InstantiationAwareBeanPostProcessor这种后处理器的postProcessBeforeInstantiation方法

这是一个接口,继承自BeanPostProcessor,是后处理器的一种,在bean实例被创建之前执行,可以在实例化前方法中返回一个对象这样就会提前结束bean的创建,不走后续的逻辑。

这个resolveBeforeInstantiation的内部就是在执行实例化前,如果返回的bean不是null就会提前结束bean的创建

上边的applyBeanPostProcessorsBeforeInstantiation就是在执行实例化前方法,大部分情况其内部都返回null,才会执行后续的创建bean逻辑,如果返回的不是null就会提前结束bean的创建,并且这里会提前执行实例化后方法,也是同一个接口中的方法。

要注意的是spring创建bean的过程中执行的后处理器,也就是BeanPostProcessor,或者其子接口的实现类,是在ApplicationContext类型容器的refresh方法中注册到AbstractBeanFactory的成员变量beanPostProcessors中的,需要执行的时候会从这个成员变量中获取,继续进到applyBeanPostProcessorsBeforeInstantiation方法的内部就可以看到。

实例化前方法执行完后就开始执行真正的实例化逻辑,doCreateBean方法

2.3.2 doCreateBean 实例化

实例化前执行完后执行实例化方法

继续看看这个doCreateBean内部,这个方法还是在AbstractAutowireCapableBeanFactory#doCreateBean

这个方法中主要完成了这几个步骤

2.3.2.1 实例化 创建bean的实例 createBeanInstance

doCreateBean方法开始有一句createBeanInstance(beanName, mbd, args);,在这个方法的内部通过反射创建出一个对象,完成目标bean的实例化。

上边只是把对象创建出来了,bean中的各种属性都还没有值,后续的处理中会对bean的属性进行填充。

2.3.2.2 执行后处理器 MergedBeanDefinitionPostProcessor

这个接口MergedBeanDefinitionPostProcessor 也是BeanPostProcessor的子接口,在上边创建完对象后就会开始执行这个后处理器的postProcessMergedBeanDefinition方法,可以对bean对象进行后续处理。

比如有一个实现类AutowiredAnnotationBeanPostProcessor,这个类用来解析类中的Autowired Value,

就是在这里调用AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition方法来完成对这俩注解的解析,

然后后续的处理过程中会根据解析结果进行属性注入。

上边红色框就是在执行后处理的代码,同样的其内部也是从AbstractBeanFactory的成员变量beanPostProcessors中按接口类型去获取对应的实现类然后执行。

这种后处理器执行完后就要进行bean对象的属性填充。

2.3.2.3 把半成品bean加入三级缓存

在这块,spring为了解决bean之间循环依赖的问题,使用三级缓存来解决,在这里会把半成品bean放进三级缓存中。

上边红色框就是在往三级缓存中放入bean,可以看到三级缓存中放入的是一个lambda表达式,由此可以推测从三级缓存中根据beanName拿到东西后需要调用方法触发lambda才会获取到放入的bean的引用,这块后边讲到三级缓存时再详细看。

2.3.2.4 属性填充 populateBean

这个方法AbstractAutowireCapableBeanFactory#populateBean从整体上看是完成对bean属性进行填充的功能,主要有这么几个步骤

(1) 执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation,也就是实例化后方法

(2)根据bean中属性的名称和类型尝试进行自动注入。当然前提是开启了这个功能,比如在bean标签上使用autowire属性开启

<bean id="person" class="com.lyy.vo.Person" autowire="byType">
</bean>

(3) 执行InstantiationAwareBeanPostProcessor#postProcessProperties方法,其中上边提到的Autowired注解修饰的属性就是在这个方法中被注入其他bean对象的,当然实际执行的是实现类AutowiredAnnotationBeanPostProcessor#postProcessProperties方法

(4) 应用xml文件中使用property标签进行的属性注入

<bean id="person" class="com.lyy.vo.Person">
        <property name="name" value="lyy"/>
 </bean>

像上边这个配置,perosn中name属性的赋值就是在这块进行的。

然后属性填充方法就结束了,注意一下spring刚开始设计的时候是基于xml配置的,所以源码中的主线功能都是跟着xml配置走的,对注解的支持实际是通过各种后处理器来实现的。

2.3.2.5 初始化 initializeBean

AbstractAutowireCapableBeanFactory#initializeBean方法完成对bean的初始化,在上边属性填充的基础上接着进行处理。

(1) invokeAwareMethods(beanName, bean);对spring提供的各种aware接口进行处理

(2) 再次执行一个后处理方法BeanPostProcessor#postProcessBeforeInitialization

就是俗称的初始化前方法

(3) 执行 InitializingBean#afterPropertiesSet方法,就是俗称的初始化方法

(4)再次执行一个后处理器方法 BeanPostProcessor#applyBeanPostProcessorsAfterInitialization

就是俗称的初始化后

三、总结

到这里spring创建bean的过程大部分就执行完了,以上列出了bean生命周期中的一些步骤,看着很多,实际上可以简单总结为 这几类步骤

(1) 执行后处理的方法 就是BeanPostProcessor还有其各种子接口的实现类中的方法

(2) 创建bean的实例对象

(2)bean对象的属性填充

(4) 处理各种aware接口

(5) 执行InitializingBean接口的实现类方法

要注意的是我们平时描述bean的生命周期时看着好像是一个线性的执行过程,但实际各个步骤之间是一个方法调用的嵌套关系,也就是上面哪些步骤是互相嵌套着的,并不是同一个层级的东西,这个需要注意下。