Spring Bean的生命周期(一) - 概述
最后更新于
最后更新于
如果这只是一个普通的 java 的对象,那这个图示完全成立、合理。不过在 SpringFramework 中,这个流程就不够完整了,我们来回忆一下前面学习的内容。
在 bean 的创建之前,bean 是以 BeanDefinition
的方式被描述和注册在 BeanFactory
的(准确的说是注册在 BeanDefinitionRegistry
中),这个时候虽然 bean 还没有被创建,但是 BeanFactory
中已经存有 bean 对应的 BeanDefinition
了,所以在 bean 的实例化之前,还应该有 **BeanDefinition**
阶段。
BeanDefinition
也不是凭空出现的,要么是解析了配置文件(比如xml),要么是解析了配置类(比如@Configuration
),要么有人编程式(注解)的注入了 BeanDefinition
,所以如果纵观整个 bean 的生命周期,在 BeanDefinition
阶段之前,还应该有 BeanDefinition
的来源和加载阶段。
上面咱也说了,bean 的实例化需要先有 BeanDefinition
的信息,所以 BeanDefinition
都是怎么来的呢?这里我们来理一下。
声明式注入 BeanDefinition
@Configuration
+ @Bean
@Component
+ @ComponentScan
@Import
配置式注入 BeanDefinition
<bean>
标签声明
编程式注入 BeanDefinition
ImportBeanDefinitionRegistrar
手动构造 BeanDefinition
注入
借助 BeanDefinitionRegistryPostProcessor
注入
通过上述的方式,就可以把 BeanDefinition
注入到 BeanFactory
中了。
根据前面后置处理器学过的内容,我们可以知道 BeanDefinition
都构造好之后,是不会立即注册到 BeanFactory
的,这中间有一步执行 BeanDefinitionRegistryPostProcessor
的动作,等这些 BeanDefinitionRegistryPostProcessor
都执行完 postProcessBeanDefinitionRegistry
方法后,BeanDefinition
才会注册到 BeanFactory
。
这个动作之后,下一步则是执行 BeanFactoryPostProcessor
的 postProcessBeanFactory
方法了,这个阶段可以给 BeanDefinition
修改配置信息,添加注入的依赖项,给属性赋值等操作。
这一步执行完毕后,BeanDefinition
就不会再动了,BeanDefinition
的阶段也就算结束了。
从 AbstractApplicationContext
的 refresh
方法中找到执行步骤,其中第 11 步 finishBeanFactoryInitialization
方法就是初始化 bean 实例的动作了:
这一步的动作非常多,它会将所有还没有实例化的、非延迟加载的单实例 bean 都创建出来。而创建一个 bean 的流程也是非常多且复杂,总体可以分为以下几个步骤。
bean 的实例化阶段,第一步并不是直接创建对象,还记得之前的 BeanDefinition
合并那个特性吗?如果一个 <bean>
有继承另外一个 <bean>
定义,则会形成父子定义。这种情况下,创建 bean 的时候就需要读取父 bean 的定义,合并为最终的 RootBeanDefinition
。
合并完 BeanDefinition
,下一步才是真正的实例化 bean ,不过这里要注意一个问题:如果 bean 是一个 FactoryBean
,这里该如何处理呢?是只创建 FactoryBean
本身?还是连 FactoryBean
创建的真实对象一起创建?
除了考虑 FactoryBean
之外,还有一个要考虑的因素是缓存问题。咱在一开始学 IOC 的由来时,就知道 BeanFactory
中可以缓存单实例 bean ,那么在 Spring 中是如何处理单实例 bean 在实例化后的缓存呢?
bean 对象实例化完成后,里面所有的成员都是空的,接下来的步骤就是属性赋值和依赖注入了。由于这部分逻辑属于 bean 实例已经创建,所以小册在这里将该步骤划到下面的 bean 初始化部分。
在这个环节,最重要的是如何处理 <bean>
中的 <property>
标签、bean 中的 @Value
、@Autowired
等自动注入的注解。
BeanPostProcessor
的扩展 InstantiationAwareBeanPostProcessor
可以在 bean 的实例化之后、初始化之前执行 postProcessAfterInstantiation
方法,以及 postProcessProperties
( postProcessPropertyValues
) 方法完成属性赋值!所以我们就可以断定,这个环节一定是 InstantiationAwareBeanPostProcessor
在工作。
这个阶段相信小伙伴们都非常熟悉了,这部分就不多啰嗦了吧,后面直接翻源码看看底层原理就完事了。
之前在 bean 的生命周期中没有提到一个接口:Lifecycle
,之所以没有在那儿提,是考虑到 Lifecycle
的执行是依照 ApplicationContext
的生命周期而来,两者是相互关联的,所以小册把 Lifecycle
接口的讲解安排到了这里。
先简单说说 Lifecycle
的触发时机吧。往上翻一翻 refresh
方法的 try 块最后一行:finishRefresh
,它在里面会找出所有实现了 Lifecycle
接口的 bean ,并调用它们的 start
方法(所以是不是回想起了第 16 章的 ContextStartedEvent
事件)。注意此时所有实现了 Lifecycle
的非延迟加载的单实例 bean 都已经加载完成了,是可以正常调用 start
方法的。
一般实现 Lifecycle
的 start
方法多用于建立连接、加载资源等等操作,以备程序的运行期使用。
so ,这个阶段 ApplicationContext
就会完成所有 Lifecycle
类型的 bean 的 start
方法调用,对于一个 bean 的生命周期而言,就已经到了正常存活期了。
说完了 bean 的加载和初始化,当 ApplicationContext
关闭时,这些 bean 也是需要销毁的,而这个销毁流程我们也要来研究一下。
相比较于 bean 的创建和初始化,销毁部分就变得比较简单了,我们可以先对整个 ApplicationContext
的关闭有一个整体的了解。
关闭 ApplicationContext
会顺序执行以下几步:
广播容器关闭事件
学过的 ContextClosedEvent
事件
通知所有实现了 Lifecycle
的 bean 回调 close
方法
销毁所有 bean
关闭 BeanFactory
标记本身为不可用,
而这里面有关 bean 的销毁,就只包含 2 、3 两步,下面分述。
与上面的 bean 启动一致,如果一个 bean 实现了 Lifecycle
接口,此处会回调 bean 的 close
方法。由于此时 bean 的销毁回调方法还没有执行,所以在销毁阶段,Lifecycle
的执行时机是最靠前的。
一般实现 Lifecycle
的 close
方法多用来关闭连接、释放资源等操作,因为程序终止了,这些资源也就没必要持有了。
bean “停止” 后,接下来就是对应于 bean 初始化阶段的三种生命周期回调的销毁部分了。不过这里面有一个不同点:BeanPostProcessor
的回调包含 bean 的初始化之前和初始化之后,但 DestructionAwareBeanPostProcessor
只包含 bean 销毁回调之前的动作,没有之后。