1. Bean 的生命周期概述
区别于一般的 Java 目标需求经过 new
创立目标,Spring 的 Bean 由 IoC 容器进行实例化、拼装以及办理的。也便是说 Bean 的生命周期完全由 IoC 容器控制。
Spring 容器只能办理 单例(singleton) 效果域的 Bean 的完好生命周期,对于 原型(prototype) 效果域的 Bean,Spring 容器只创立 bean 的实例后便会回来给用户,剩下的生命周期由用户控制。所以 Bean 的生命周期主要指的是 singleton 效果域 的 Bean。
为什么要了解 Bean 的生命周期?
经过了解 Bean 的生命周期能够了解 Bean 是什么时候被创立的,什么时候初始化,什么时候被毁掉以及整个 Bean 的生命周期中哪些阶段能够运用哪些增加办法。
这样在实际开发中,能够使用 Bean 的生命周期的指定时间完结一些自定义的操作。一起面试中 Spring Bean 的生命周期也是常问的一个内容,所以很有必要了解一下。
Bean 的生命周期主要包括四个部分
- 实例化(Instantiation)
- 特点赋值(Populate)
- 初始化(Initialization)
- 毁掉(Destruction)
以 AbstractApplicationContext
的 refresh()
办法为进口,AbstractAutowireCapableBeanFactory
的 doCreateBean
办法完结对 Bean 的实例化、特点注入以及初始化。(详细流程能够看 3.2 的详细流程整理)
以AbstractApplicationContext
的 close()
办法为进口,在 DisposableBeanAdapter
的 destory()
办法完结对 Bean 的毁掉。(详细流程能够看 3.2 的详细流程整理)
2. 相关接口及办法
Bean 的生命周期中运用到了 Aware
类型的相关接口、InitializingBean
/DisposableBean
接口以及一些起到增强效果的接口。了解这些接口能够协助大家更好地了解 Bean 的生命周期以及更好地拓宽定制自己的 Bean 目标。
2.1 各种 Aware
类型的接口
完成 Aware
接口的目的是让程序能够拿到 Spring 容器的当时的运行环境(如当时 Bean 的称号、当时的 BeanFactory、当时的 ApplicationContext 等等资源)。这类接口的调用机遇是在 Bean 实例化、特点注入之后,初始化之前。
接下来列出一些常用的子接口,有爱好的能够从源码中检查还有哪些接口(基本都是见名知意):
BeanNameAware
接口
接口中只要一个办法 void setBeanName(String name)
用于获取当时 Bean 的称号。
BeanFactoryAware
接口
接口中只要一个办法 void setBeanFactory(BeanFactory beanFactory)
用于获取当时的 BeanFactory。
ApplicationContextAware
接口
接口中只要一个办法 void setApplicationContext(ApplicationContext applicationContext)
用于获取当时的 ApplicationContext。
2.2 InitializingBean
/DisposableBean
接口
完成InitializingBean
/DisposableBean
接口能够完成自定义初始化办法以及毁掉办法。这两个接口的调用机遇分别在初始化阶段与毁掉阶段。
InitializingBean
接口
接口中只要一个办法 void afterPropertiesSet()
用于自定义初始化行为,在特点注入阶段后履行。
DisposableBean
接口
接口中只要一个办法 void destroy()
用于自定义毁掉行为,在毁掉阶段履行。
除了接口完成办法外,还有两种能够完成自定义初始化以及毁掉的办法:
- 运用 XML 装备文件 或许 Java 装备类 对 Bean 中的
init-method
与destroy-method
特点进行装备(基于 Bean 本身的初始化和毁掉) - 运用 注解
@PostConstruct
与@PreDestroy
修饰办法(效果于servlet生命周期的注解)
2.3 增强办法
BeanFactoryPostProcessor
接口
完成该接口能够增强的方面是:在 BeanFactory 已经初始化而 Bean 实例化之前调用该接口的办法能够修正或增加 Bean 的定义。所以该接口的调用机遇是在 Bean 实例化之前。
接口中只要一个办法 void postProcessBeanFactory(ConfigurableListableBeanFactory var1)
用于在 Bean 实例化之前修正 Bean 的定义。
BeanPostProcessor
接口
完成该接口能增强的方面是:在 Bean 实例化后,在初始化阶段的前后自定义行为。能够依据接口办法中的参数来挑选需求自定义行为的 Bean。该接口的调用机遇是在 初始化阶段的前后。
该接口有两个办法分别在初始化前和初始化后履行:
-
postProcessBeforeInitialization(Object bean, String beanName)
:初始化前调用 -
postProcessAfterInitialization(Object bean, String beanName)
:初始化后调用
InstantiationAwareBeanPostProcessor
接口
完成该接口能增强的方面是:在目标 Bean 实例化的前后能够自定义行为以及在特点注入前能够修正 Bean 的特点设置。
该接口有三个办法(其实还有两个来自于继承 BeanPostProcessor
接口的办法):
-
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
:在 Bean 实例化之前调用 -
postProcessAfterInstantiation(Object bean, String beanName)
:在 Bean 实例化之后调用 -
postProcessProperties(PropertyValues pvs, Object bean, String beanName)
:在 Bean 实例化之后,特点注入之前调用
3. 浅谈生命周期的详细流程
3.1 经过例子展示详细流程
经过一个例子来表现 Bean 的生命周期 的详细流程以及相关接口对应的切入机遇
MyBean 类
/**
* Bean目标
* @author 单程车票
*/
public class MyBean implements InitializingBean, DisposableBean, BeanNameAware {
private Integer id;
public MyBean(Integer id) {
this.id = id;
System.out.println("进程3(实例化阶段中):调用结构办法,当时id为" + this.id + "(能够发现id此刻并不是装备文件的1001,而是增强办法修正后的1002)");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
System.out.println("进程6(特点注入阶段中):特点注入阶段,注入后id为" + this.id + "(能够发现id此刻并不是装备文件的1003,而是增强办法修正后的1004)");
}
@Override
public void setBeanName(String name) {
System.out.println("进程7(特点注入阶段后):获取当时Bean的称号:" + name);
}
public void myInit() {
System.out.println("进程10(初始化阶段中):调用Bean本身特点 init-method 的初始化办法");
}
public void myDestroy() {
System.out.println("进程13(毁掉阶段中):调用Bean本身特点 destroy-method 的毁掉办法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("进程9(初始化阶段中):调用 InitializingBean接口 的初始化办法");
}
@Override
public void destroy() throws Exception {
System.out.println("进程12(毁掉阶段中):调用 DisposableBean接口 的毁掉办法");
}
}
完成 BeanFactoryPostProcessor 接口
/**
* 对实例化前进行增强
* @author 单程车票
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("myBean");
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, 1002);
// 将原本装备文件装备的值1001改为1002(这儿运用了ConstructorArgumentValues有爱好的能够自行了解一下)
beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
System.out.println("进程1(实例化阶段前): 调用 BeanFactoryPostProcessor.postProcessBeanFactory 办法进行增强,将id值改为1002");
}
}
完成 BeanPostProcessor 接口
/**
* 对初始化阶段前后进行增强
* @author 单程车票
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("myBean".equals(beanName)) {
System.out.println("进程8(特点注入阶段后,初始化阶段前):调用 BeanPostProcessor.postProcessBeforeInitialization 办法进行增强");
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("myBean".equals(beanName)) {
System.out.println("进程11(初始化阶段后):调用 BeanPostProcessor.postProcessAfterInitialization 办法进行增强");
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
完成 InstantiationAwareBeanPostProcessor 接口
/**
* 完成InstantiationAwareBeanPostProcessor接口
* @author 单程车票
*/
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("myBean".equals(beanName)) {
System.out.println("进程2(实例化阶段前):调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 办法进行增强");
}
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("myBean".equals(beanName)) {
System.out.println("进程4(实例化阶段后):调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation 办法进行增强");
}
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("myBean".equals(beanName)) { // 对 Bean 再次修正 id 特点
PropertyValue propertyValue = pvs.getPropertyValue("id");
assert propertyValue != null;
propertyValue.setConvertedValue(1004);
System.out.println("进程5(实例化阶段后,特点注入阶段前):调用 InstantiationAwareBeanPostProcessor.postProcessProperties 办法进行增强,将id特点改为1004");
}
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}
XML 装备文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 这儿需求留意加上 Bean本身的初始化办法和毁掉办法 -->
<bean id="myBean" class="com.xqsr.springtest.bean.MyBean" init-method="myInit" destroy-method="myDestroy">
<!-- 这儿需求留意结构器(实例化)的id值为1001 -->
<constructor-arg name="id" value="1001"/>
<!-- 这儿需求留意setter(特点注入)的id值为1001 -->
<property name="id" value="1003"/>
</bean>
<bean class="com.xqsr.springtest.bean.MyBeanFactoryPostProcessor"/>
<bean class="com.xqsr.springtest.bean.MyBeanPostProcessor"/>
<bean class="com.xqsr.springtest.bean.MyInstantiationAwareBeanPostProcessor"/>
</beans>
测验类
/**
* 测验类
* @author 单程车票
*/
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
MyBean bean = (MyBean) applicationContext.getBean("myBean");
((AbstractApplicationContext) applicationContext).close();
}
}
履行成果
3.2 详细流程整理
经过上面的例子能够整理出下面这张 Bean 的生命周期 详细流程图
接下来从源码的角度对流程图的每一个部分进行分析
从源码看
BeanFactoryPostProcessor # postProcessBeanFactory()
在实例化前履行
经过从 refresh()
进口进入依照上面图中的流程能够找到调用 postProcessBeanFactory()
的办法,该办法是在 invokeBeanFactoryPostProcessors(beanFactory)
进入的,而实例化阶段是从 finishBeanFactoryInitialization(beanFactory)
进入的,所以能够阐明 BeanFactoryPostProcessor # postProcessBeanFactory()
要先于实例化履行。
从源码看
InstantiationAwareBeanPostProcessor # postProcessBeforeInstantiation()
在实例化前履行
经过上面的流程图能够找到调用 postProcessBeforeInstantiation()
的办法是在 resolveBeforeInstantiation(beanName, mbdToUse)
进入的,而实例化阶段是在 doCreateBean(beanName, mbdToUse, args)
进入的,所以能够阐明 postProcessBeforeInstantiation()
要先于实例化履行。
从源码看 实例化履行方位 与 特点注入履行方位
实例化阶段发生在 AbstractAutowireCapableBeanFactory
的 createBeanInstance()
办法中。
特点注入阶段发生在 AbstractAutowireCapableBeanFactory
的 populateBean()
办法中。
从源码看
InstantiationAwareBeanPostProcessor # postProcessAfterInstantiation()
与InstantiationAwareBeanPostProcessor # postProcessPropertyValues()
特点注入阶段前履行
经过上面的流程图能够找到 postProcessAfterInstantiation()
与 postProcessPropertyValues()
在 populateBean()
特点注入办法内被调用。
-
postProcessAfterInstantiation()
办法假如找到指定的 bean 就会回来 false,会直接回来不再履行后续办法内容,也便是说后续的特点填充和依赖注入就不会被履行,所以能够看出postProcessAfterInstantiation()
履行在特点注入阶段前。 -
postProcessPropertyValues()
办法相同发生在 特点填充 之前,假如回来null则不会履行后续的特点填充,假如不会为null,阐明有额定增加的特点需求填充,后续办法会履行特点填充。
从源码看 初始化阶段及其前后发生的调用
依据上面的流程图能够找到初始化阶段进入的进口 initializeBean()
办法,详细代码如下图:
-
先看
Aware
接口的调用除了上面
BeanXXXAware
接口的调用,如ApplicationContextAware
接口的调用是发生在applyBeanPostProcessorsBeforeInitialization
办法中的,也便是是经过BeanPostProcessor的postProcessBeforeInitialization()
完成调用的,详细的能够自己跟一下源码。 -
BeanPostProcessor
的两个完成办法这两个完成办法分别经过
applyBeanPostProcessorsBeforeInitialization
与applyBeanPostProcessorsAfterInitialization
办法调用,也能够看出一个在初始化前一个在初始化后履行。 -
invokeInitMethods
初始化办法invokeInitMethods
初始化办法中调用了InitializingBean
的自定义初始化办法 与 Bean本身特点中的init-method
指定的办法。
从源码看 毁掉阶段
依据上面的流程图最终会找到 DisposableBeanAdapter
的 destory()
办法,详细代码如下:
经过 destory()
办法也能够看到 毁掉阶段 先履行 DisposableBean
的毁掉办法,再履行 Bean 本身特点 destory-method
指定的办法。