Spring Bean的生命周期(一) - 概述
1. 如何全面理解bean的生命周期

如果这只是一个普通的 java 的对象,那这个图示完全成立、合理。不过在 SpringFramework 中,这个流程就不够完整了,我们来回忆一下前面学习的内容。
1.1 bean的创建之前
在 bean 的创建之前,bean 是以 BeanDefinition 的方式被描述和注册在 BeanFactory 的(准确的说是注册在 BeanDefinitionRegistry 中),这个时候虽然 bean 还没有被创建,但是 BeanFactory 中已经存有 bean 对应的 BeanDefinition 了,所以在 bean 的实例化之前,还应该有 **BeanDefinition** 阶段。
1.2 BeanDefinition的由来
BeanDefinition 也不是凭空出现的,要么是解析了配置文件(比如xml),要么是解析了配置类(比如@Configuration),要么有人编程式(注解)的注入了 BeanDefinition ,所以如果纵观整个 bean 的生命周期,在 BeanDefinition 阶段之前,还应该有 BeanDefinition 的来源和加载阶段。
2. BeanDefinition阶段的主要工作
2.1 BeanDefinition的来源
上面咱也说了,bean 的实例化需要先有 BeanDefinition 的信息,所以 BeanDefinition 都是怎么来的呢?这里我们来理一下。
声明式注入
BeanDefinition@Configuration+@Bean
@Configuration
public class QuickStartConfiguration {
@Bean
public Person person() {
return new Person();
}
}@Component+@ComponentScan
@Configuration
@ComponentScan("com.linkedbear.spring.annotation.c_scan")
public class ComponentScanConfiguration@Import
@Import({Boss.class, BartenderConfiguration.class})
public @interface EnableTavern配置式注入
BeanDefinition<bean>标签声明
<bean id="person" class="com.linkedbear.spring.basic_dl.a_quickstart_byname.bean.Person"/>编程式注入
BeanDefinitionImportBeanDefinitionRegistrar
public class WaiterRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition("waiter", new RootBeanDefinition(Waiter.class));
}
}手动构造
BeanDefinition注入
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
BeanDefinition personDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class)
.addPropertyValue("name", "zhangsan").getBeanDefinition();
ctx.registerBeanDefinition("person", personDefinition);
ctx.refresh();借助
BeanDefinitionRegistryPostProcessor注入
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition("animalNameSetterPostProcessor",
new RootBeanDefinition(AnimalNameSetterPostProcessor.class));
}通过上述的方式,就可以把 BeanDefinition 注入到 BeanFactory 中了。
2.2 BeanDefinition的后置处理
根据前面后置处理器学过的内容,我们可以知道 BeanDefinition 都构造好之后,是不会立即注册到 BeanFactory 的,这中间有一步执行 BeanDefinitionRegistryPostProcessor 的动作,等这些 BeanDefinitionRegistryPostProcessor 都执行完 postProcessBeanDefinitionRegistry 方法后,BeanDefinition 才会注册到 BeanFactory 。

这个动作之后,下一步则是执行 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法了,这个阶段可以给 BeanDefinition 修改配置信息,添加注入的依赖项,给属性赋值等操作。

这一步执行完毕后,BeanDefinition 就不会再动了,BeanDefinition 的阶段也就算结束了。
3. bean实例阶段的内容
从 AbstractApplicationContext 的 refresh 方法中找到执行步骤,其中第 11 步 finishBeanFactoryInitialization 方法就是初始化 bean 实例的动作了:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
// 11. 初始化剩余的单实例bean
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
// catch ......
finally {
resetCommonCaches();
}
}
}这一步的动作非常多,它会将所有还没有实例化的、非延迟加载的单实例 bean 都创建出来。而创建一个 bean 的流程也是非常多且复杂,总体可以分为以下几个步骤。
3.1 BeanDefinition的合并
bean 的实例化阶段,第一步并不是直接创建对象,还记得之前的 BeanDefinition 合并那个特性吗?如果一个 <bean> 有继承另外一个 <bean> 定义,则会形成父子定义。这种情况下,创建 bean 的时候就需要读取父 bean 的定义,合并为最终的 RootBeanDefinition 。
3.2 bean的实例化
合并完 BeanDefinition ,下一步才是真正的实例化 bean ,不过这里要注意一个问题:如果 bean 是一个 FactoryBean ,这里该如何处理呢?是只创建 FactoryBean 本身?还是连 FactoryBean 创建的真实对象一起创建?
除了考虑 FactoryBean 之外,还有一个要考虑的因素是缓存问题。咱在一开始学 IOC 的由来时,就知道 BeanFactory 中可以缓存单实例 bean ,那么在 Spring 中是如何处理单实例 bean 在实例化后的缓存呢?
3.3 属性赋值+依赖注入
bean 对象实例化完成后,里面所有的成员都是空的,接下来的步骤就是属性赋值和依赖注入了。由于这部分逻辑属于 bean 实例已经创建,所以小册在这里将该步骤划到下面的 bean 初始化部分。
在这个环节,最重要的是如何处理 <bean> 中的 <property> 标签、bean 中的 @Value 、@Autowired 等自动注入的注解。
BeanPostProcessor 的扩展 InstantiationAwareBeanPostProcessor 可以在 bean 的实例化之后、初始化之前执行 postProcessAfterInstantiation 方法,以及 postProcessProperties ( postProcessPropertyValues ) 方法完成属性赋值!所以我们就可以断定,这个环节一定是 InstantiationAwareBeanPostProcessor 在工作。
3.4 bean的初始化
这个阶段相信小伙伴们都非常熟悉了,这部分就不多啰嗦了吧,后面直接翻源码看看底层原理就完事了。
3.5 bean的启动
之前在 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 也是需要销毁的,而这个销毁流程我们也要来研究一下。
4. bean销毁阶段的内容
相比较于 bean 的创建和初始化,销毁部分就变得比较简单了,我们可以先对整个 ApplicationContext 的关闭有一个整体的了解。
关闭 ApplicationContext 会顺序执行以下几步:
广播容器关闭事件
学过的
ContextClosedEvent事件
通知所有实现了
Lifecycle的 bean 回调close方法销毁所有 bean
关闭 BeanFactory
标记本身为不可用,
而这里面有关 bean 的销毁,就只包含 2 、3 两步,下面分述。
4.1 bean的停止
与上面的 bean 启动一致,如果一个 bean 实现了 Lifecycle 接口,此处会回调 bean 的 close 方法。由于此时 bean 的销毁回调方法还没有执行,所以在销毁阶段,Lifecycle 的执行时机是最靠前的。
一般实现 Lifecycle 的 close 方法多用来关闭连接、释放资源等操作,因为程序终止了,这些资源也就没必要持有了。
4.2 bean的销毁回调
bean “停止” 后,接下来就是对应于 bean 初始化阶段的三种生命周期回调的销毁部分了。不过这里面有一个不同点:BeanPostProcessor 的回调包含 bean 的初始化之前和初始化之后,但 DestructionAwareBeanPostProcessor 只包含 bean 销毁回调之前的动作,没有之后。
最后更新于
这有帮助吗?