我们所说的Bean的生命周期指的是从Bean的创建、初始化、使用Bean、销毁的整个过程。而IOC容器就是负责管理Bean的整个生命周期。实际上Bean的生命周期在容器启动的时候就已经开始了,严格来说,你可以认为容器启动时,从注解配置读取器读取标有注解的类,转换为BeanDefinition对象时,Bean的生命周期就已经开始了。打个比方,小宝宝的生命的起点,并不是说从出生落地开始算的,而是从妈妈肚子里面,基本上可以算是生命已经开始了。
我们在之前的IOC容器创建过程的文章中详细说明了容器的初始化和容器刷新的流程。我们说在执行refresh()方法刷新容器时,第11个阶段是创建剩余的所有单实例Bean
首先遍历所集合中所有的Bean,根据Bean的name调用getBean()方法获取这个Bean
getBean()
方法进一步调用doGetBean()
方法
拿到bean的名字之后,先调用getSingleton()
方法获取缓存中的单实例bean,如果能获取到,就说明这个bean之前已经被创建过了,因为所有创建过的单实例bean都会被缓存起来。
注意!如果缓存中获取不到,才算是真正开始创建Bean对象的流程!!!
首先标记当前bean已被创建,防止多线程创建同一个bean
然后获取bean定义信息,以及当前bean依赖的其它bean,如果有依赖就会调用getBean()
方法把依赖的bean先创建出来
如果当前bean是单实例bean,就会启动单实例bean创建流程,会调用getSingleton()
方法通过工厂的getObject()
方法调用createBean()
来创建bean。也就是说真正执行创建Bean的方法是这个createBean()
方法
那么接下来就来详细说一说createBean()
方法是如何创建Bean的
createBean()
会先获取bean的定义信息
然后解析bean的类型
在Bean实例化之前,createBean()
会调用resolveBeforeInstantiation()
方法,会给Bean的后置处理器一个机会,**在实例化之前,让BeanPostProcessor
先拦截返回代理对象,在实例化之前执行一些自定义逻辑,同时也会在实例化之后执行一些自定义逻辑。**也就是说,可以利用Bean的后置处理器,在Bean实例化前后的时间点,去执行一些我们自定义的操作逻辑。
如果说在这个Bean实例化之前,这个BeanPostProcessor后置处理器返回的代理对象不为null,就会直接返回这个代理对象。此时相当于跳过了容器默认的实例化过程,用这个代理对象替代了本该实例化的Bean对象。
如果前面的resolveBeforeInstantiation()
方法没有返回一个代理对象,就会调用doCreateBean()
方法去创建Bean对象
实际上这个doCreateBean()
方法会调用createBeanInstance()
方法创建一个bean实例
createBeanInstance()
方法利用工厂方法或者对象的构造器创建出bean实例
doCreateBean()
方法完成bean的创建之后,会调用populateBean()
为创建出来的bean进行属性赋值。上面我们所说的由于直接返回代理对象,没有执行属性赋值,可以防止恶意的属性注入操作。
在赋值之前,会先获取BeanPostProcessor后置处理器,在实例化之后,初始化之前,利用这个后置处理器执行一些拦截操作。然后才是进行属性赋值。
完成属性赋值之后,会调用initializeBean()
方法来初始化bean
initializeBean()
方法会调用invokeAwareMethods()
方法,执行各种实现了Aware
接口的方法,比如设置bean的name、类加载器、beanFactory等信息。
然后调用applyBeanPostProcessorsBeforeInitialization()
方法,后置处理器也会在bean初始化之前进行拦截
初始化之前的后置处理器执行完之后,就会调用invokeInitMethods()
方法,执行初始化方法
invokeInitMethods()
方法执行bean的初始化操作,执行那些实现了InitializingBean
初始化接口,或者那些自定义的初始化的方法(使用注解或者init-method属性)
初始化结束之后,还会调用applyBeanPostProcessorsAfterInitialization()
方法,执行初始化之后的后置处理器操作
至此bean的初始化完成
初始化执行完成之后,会调用registerDisposableBeanIfNecessary()
方法注册bean的销毁方法,容器关闭的时候或者移除这个Bean的时候会调用销毁方法。
至此doCreateBean()
方法执行结束,返回一个bean实例。整个doCreateBean()
包含了实例化Bean、属性赋值、初始化Bean、注册销毁方法。
所以Spring容器的启动伴随着Bean生命周期的开始,整个Bean的生命周期如下图所示: