文章目录
夯实Spring系列|第十四章:Spring Bean 生命周期-下篇
本章说明
本文是 Spring Bean 生命周期系列的最后一篇,会对 Spring Bean 初始化阶段以及后面的销毁阶段进行分析和讨论。Aware 回调源码其实是在 initializeBean 方法中 (初始化 Bean 阶段),所以也可以当成是 Spring Bean 初始化阶段。
1.项目环境
- jdk 1.8
- spring 5.2.2.RELEASE
- github 地址:https://github.com/huajiexiewenfeng/thinking-in-spring
- 本章模块:bean-lifecycle
2.Spring Bean Aware 接口回调阶段
Spring Aware 接口(此接口顺序也是源码的回调执行顺序)
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
- EnvironmentAware
- EmbeddedValueResovlerAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
2.1 示例改造1
UserHolder 分别实现 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware 三个回调接口
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
private User user;
private Integer number;
private String description;
public UserHolder(User user) {
this.user = user;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "UserHolder{" +
"user=" + user +
", number=" + number +
", description='" + description + '\'' +
", beanName='" + beanName + '\'' +
'}';
}
private ClassLoader classLoader;
private BeanFactory beanFactory;
private String beanName;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
}
使用之前的 BeanInstantiationLifecycleDemo 示例代码,执行结果
UserHolder{user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}, number=1, description='The user holder v2', beanName='userHolder'}
2.2 源码分析1
AbstractAutowireCapableBeanFactory#doCreateBean 595 行,同样还是 doCreateBean 方法,但是之前是属性赋值阶段 populateBean,现在是 initializeBean 阶段。
继续往下
源码位置 AbstractAutowireCapableBeanFactory#invokeAwareMethods,通过源码我们可以看到分别对 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 进行判断。
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2.3 ApplicationContext 生命周期 Aware 回调
继续改造上面的示例
UserHolder,我们再实现一个 EnvironmentAware 回调
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware {
private User user;
private Integer number;
private String description;
public UserHolder(User user) {
this.user = user;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "UserHolder{" +
"user=" + user +
", number=" + number +
", description='" + description + '\'' +
", beanName='" + beanName + '\'' +
", environment=" + environment +
'}';
}
private ClassLoader classLoader;
private BeanFactory beanFactory;
private String beanName;
private Environment environment;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
执行结果:
UserHolder{user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}, number=1, description='The user holder v2', beanName='userHolder', environment=null}
可以看到 environment=null,setEnvironment() 打上断点,也不会执行,说明 EnvironmentAware 没有被回调。
其实原因是这些 Aware 回调接口是 ApplicationContext 生命周期中的,并不在 BeanFactory 生命周期中,这是 BeanFactory 和 ApplicationContext 的一个具体区别之一。
2.4 示例改造2
所以我们这里需要再对示例代码进行改造触发 ApplicationContext 生命周期中
/**
* Bean 实例化生命周期
*/
public class BeanInstantiationLifecycleDemo {
public static void main(String[] args) {
executeBeanFactory();
System.out.println("------------------");
executeApplicationContext();
}
private static void executeApplicationContext(){
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(locations);
//第一种添加 BeanpostBeanProcess 实现方式:
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
// beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//第二种添加 BeanpostBeanProcess 实现方式:
//将 <bean class="com.huajie.thinking.in.spring.bean.lifecycle.MyInstantiationAwareBeanPostProcess"/> 配置在 xml 中
applicationContext.refresh();
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
System.out.println(userHolder);
applicationContext.close();
}
private static void executeBeanFactory(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//内部类 无法添加 ApplicationContextAwareProcessor
// beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(beanFactory));
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
// System.out.println("Bean 定义的数量: " + count);
// String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
// Stream.of(beanDefinitionNames).forEach(System.out::println);
User user = beanFactory.getBean("user", User.class);
SuperUser superUser = beanFactory.getBean("superUser", SuperUser.class);
// 构造器注入是按照类型注入,resolveDependency
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
System.out.println(userHolder);
}
}
将 MyInstantiationAwareBeanPostProcess 独立成一个单独的类,不在作为内部类
bean-constructor-injection.xml 加入 MyInstantiationAwareBeanPostProcess 配置
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="com.huajie.thinking.in.spring.bean.lifecycle.MyInstantiationAwareBeanPostProcess"/>
<bean id="userHolder" class="com.huajie.thinking.in.spring.bean.lifecycle.domain.UserHolder"
autowire="constructor">
<!--<property name="number" value="1"/>-->
<property name="description" value="The user holder" />
</bean>
</beans>
执行结果:
UserHolder{user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}, number=1, description='The user holder v2', beanName='userHolder', environment=null}
------------------
UserHolder{user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}, number=1, description='The user holder v2', beanName='userHolder', environment=StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}}
可以看到 BeanFactory 的方式无法回调 EnvironmentAware,而 ApplicationContext 可以。
2.5 源码分析2
我们看一下 AbstractApplicationContext#prepareBeanFactory 中如何进行 Aware 回调
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
...
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
关键代码 ApplicationContextAwareProcessor 我们再看下 ApplicationContextAwareProcessor 具体实现
ApplicationContextAwareProcessor#invokeAwareInterfaces
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
代码和 BeanNameAware 的回调如出一辙。
3.Spring Bean 初始化前阶段
初始化前阶段已完成以下三个阶段
- Bean 实例化
- Bean 属性赋值
- Bean Aware 接口回调
方法回调
- BeanPostProcessor#postProcessBeforeInitialization
3.1 示例代码
为了打印方便我们可以把 UserHolder#toString 方法改造一下
@Override
public String toString() {
return "UserHolder{" +
"number=" + number +
", description='" + description +
", user=" + user +
'}';
}
MyInstantiationAwareBeanPostProcess 新增 postProcessBeforeInitialization 的实现
public class MyInstantiationAwareBeanPostProcess implements InstantiationAwareBeanPostProcessor {
/**
* 实例化前阶段
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "superUser") && SuperUser.class.equals(beanClass)) {
SuperUser user = new SuperUser();
user.setName("new-superUser v1");
return user;
}
return null;
}
/**
* 实例化后阶段
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "user") && User.class.equals(bean.getClass())) {
//"user" 对象不允许属性赋值(配置元信息-> 属性值)
User user = User.class.cast(bean);
user.setId(2L);
user.setName("after-superUser v2");
return false;//返回 false 表示忽略掉配置元信息,比如 <bean ...<property name = id value = 1/>
}
return true;
}
// user 跳过 Bean 属性赋值
// superUser 也是完全跳过 Bean 实例化
// 这里我们只能拦截 UserHolder
/**
* 属性赋值前阶段
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && UserHolder.class.equals(bean.getClass())) {
final MutablePropertyValues propertyValues;
// 兼容 pvs 为空的情况 pvs 对应xml中配置的 <property .../>
if (pvs instanceof MutablePropertyValues) {
propertyValues = (MutablePropertyValues) pvs;
} else {
propertyValues = new MutablePropertyValues();
}
// 此操作等价于 <property name="number" value="1"/>
propertyValues.addPropertyValue("number", "1");
if (propertyValues.contains("description")) {
// PropertyValue 无法直接覆盖,因为是 final 类型
PropertyValue description = propertyValues.getPropertyValue("description");
propertyValues.removePropertyValue("description");
propertyValues.addPropertyValue("description", "The user holder v2");
System.out.println("属性赋值前阶段 : postProcessProperties() -> The user holder v2");
}
return propertyValues;
}
return null;
}
/**
* 初始化前阶段
* 这个接口实际上是覆盖的 BeanPostProcessor 中的方法
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && UserHolder.class.equals(bean.getClass())) {
UserHolder user = UserHolder.class.cast(bean);
user.setDescription("The user holder v3");
System.out.println("初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3");
}
return bean;
}
}
调用示例 BeanInitializationLifecycleDemo
/**
* Bean 初始化生命周期
*/
public class BeanInitializationLifecycleDemo {
public static void main(String[] args) {
executeBeanFactory();
}
private static void executeBeanFactory() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
System.out.println(userHolder);
}
}
执行结果:
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
UserHolder{number=1, description='The user holder v3, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
3.2 源码分析
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 同样也是遍历我们所有的 BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 执行 postProcessBeforeInitialization 获取返回结果 如果为 null 就返回当前 bean
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
4.Spring Bean 初始化阶段
Bean 初始化(Initialization)
- @PostConstruct 标注方法
- 实现 InitializingBean 接口的 afterPropertiesSet() 方法
- 自定义初始化方法
4.1 示例改造
UserHolder 我们分别加入三种初始化的方式,需要注意的是 @PostConstruct 是 Java 通用注解,需要特殊的方式进行触发,相关文章 第九章:IoC 依赖注入(专题)-下 10.Java 通用注入原理 小节
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, InitializingBean {
private User user;
private Integer number;
private String description;
public UserHolder(User user) {
this.user = user;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@PostConstruct
public void init(){
this.description = "The userHolder v4";
System.out.println("初始化阶段 : @PostConstruct -> The user holder v4");
}
@Override
public void afterPropertiesSet() throws Exception {
this.description = "The userHolder v5";
System.out.println("初始化阶段 : afterPropertiesSet() -> The user holder v5");
}
public void customInit() throws Exception {
this.description = "The userHolder v6";
System.out.println("初始化阶段 : customInit() -> The user holder v6");
}
@Override
public String toString() {
return "UserHolder{" +
"number=" + number +
", description='" + description +
", user=" + user +
'}';
}
private ClassLoader classLoader;
private BeanFactory beanFactory;
private String beanName;
private Environment environment;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
bean-constructor-injection.xml 文件 bean 增加 init-method=“customInit” 属性
<bean id="userHolder" class="com.huajie.thinking.in.spring.bean.lifecycle.domain.UserHolder"
autowire="constructor" init-method="customInit">
<!--<property name="number" value="1"/>-->
<property name="description" value="The user holder" />
</bean>
调用示例 BeanInitializationLifecycleDemo
/**
* Bean 初始化生命周期
*/
public class BeanInitializationLifecycleDemo {
public static void main(String[] args) {
executeBeanFactory();
}
private static void executeBeanFactory() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//添加 CommonAnnotationBeanPostProcessor 触发 @PostConstruct
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
System.out.println(userHolder);
}
}
执行结果:
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
UserHolder{number=1, description='The userHolder v6, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
4.2 源码分析
从源码可以很清晰的看到 初始化前 -> 初始化 -> 初始化后 三个阶段
过程相对简单,这里就不一 一截图演示了,可对照源码位置打上断点进行调试:
- afterPropertiesSet
AbstractAutowireCapableBeanFactory#invokeInitMethods 1855 行
((InitializingBean) bean).afterPropertiesSet();
- 自定义方法
AbstractAutowireCapableBeanFactory#invokeInitMethods 1864 行
invokeCustomInitMethod(beanName, bean, mbd);
- @PostContruct
其实在初始化前的操作中就已经完成了 postProcessBeforeInitialization
InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata#invokeInitMethods 333 行
5.Spring Bean 初始化后阶段
方法回调
- BeanPostProcessor#postProcessAfterInitialization
5.1 示例改造
和初始化前的阶段一样,我们只需要重写 BeanPostProcessor 中的 postProcessAfterInitialization 方法即可
public class MyInstantiationAwareBeanPostProcess implements InstantiationAwareBeanPostProcessor {
... //省略掉之前的阶段代码
/**
* 初始化后阶段
* 这个接口实际上是覆盖的 BeanPostProcessor 中的方法
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && UserHolder.class.equals(bean.getClass())) {
UserHolder user = UserHolder.class.cast(bean);
user.setDescription("The user holder v7");
System.out.println("初始化后阶段 : postProcessAfterInitialization() -> The user holder v7");
}
return bean;
}
}
执行结果:
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
初始化后阶段 : postProcessAfterInitialization() -> The user holder v7
UserHolder{number=1, description='The user holder v7, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
5.2 源码分析
这个源代码和初始化前阶段的 applyBeanPostProcessorsBeforeInitialization 源码基本上完全一样
- 遍历所有的 BeanPostProcessor 执行 postProcessAfterInitialization 方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
5.3 小结
从上面源码分析可以看出 initializeBean 初始化 Bean 的方法依次进行了四个操作
- invokeAwareMethods(beanName, bean); //Aware回调
- applyBeanPostProcessorsBeforeInitialization //初始化前
- invokeInitMethods //初始化
- applyBeanPostProcessorsAfterInitialization //初始化后
6.Spring Bean 初始化完成阶段
方法回调
- Spring 4.1+: SmartInitializingSingleton#afterSingletonsInstantiated
6.1 示例改造
UserHolder 实现 SmartInitializingSingleton 接口
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, InitializingBean,SmartInitializingSingleton {
private User user;
private Integer number;
private String description;
public UserHolder(User user) {
this.user = user;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@PostConstruct
public void init(){
this.description = "The userHolder v4";
System.out.println("初始化阶段 : @PostConstruct -> The user holder v4");
}
@Override
public void afterPropertiesSet() throws Exception {
this.description = "The userHolder v5";
System.out.println("初始化阶段 : afterPropertiesSet() -> The user holder v5");
}
public void customInit() throws Exception {
this.description = "The userHolder v6";
System.out.println("初始化阶段 : customInit() -> The user holder v6");
}
@Override
public String toString() {
return "UserHolder{" +
"number=" + number +
", description='" + description +
", user=" + user +
'}';
}
private ClassLoader classLoader;
private BeanFactory beanFactory;
private String beanName;
private Environment environment;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void afterSingletonsInstantiated() {
this.description = "The userHolder v8";
System.out.println("初始化完成阶段 : afterSingletonsInstantiated() -> The user holder v8");
}
}
afterSingletonsInstantiated 这个方法此时还不能被回调,我们需要通过 Idea 来查找这个方法在哪里被调用过,
DefaultListableBeanFactory#preInstantiateSingletons,所以我们需要在代码中显示的调用这个方法
beanFactory.preInstantiateSingletons();
/**
* Bean 初始化生命周期
*/
public class BeanInitializationLifecycleDemo {
public static void main(String[] args) {
executeBeanFactory();
}
private static void executeBeanFactory() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//添加 CommonAnnotationBeanPostProcessor 触发 @PostConstruct
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
// 通常在 ApplicationContext 场景使用
beanFactory.preInstantiateSingletons();
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
System.out.println(userHolder);
}
}
执行结果:
user用户对象初始化...
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
初始化后阶段 : postProcessAfterInitialization() -> The user holder v7
初始化完成阶段 : afterSingletonsInstantiated() -> The user holder v8
UserHolder{number=1, description='The userHolder v8, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
6.2 备注
SmartInitializingSingleton 通常在 ApplicationContext 场景使用,因为在应用上下文启动过程中,AbstractApplicationContext#refresh 中 finishBeanFactoryInitialization(beanFactory);
会显示的调用这个 preInstantiateSingletons() 方法。
preInstantiateSingletons 在 AbstractApplicationContext 场景非常重要,有两层含义
- 初始化我们所有的 Spring Bean
- 通过 beanDefinitionNames 来遍历我们所有的 BeanDefintion,逐一进行 getBean(beanName) 操作,通过我们的 BeanDefinition 创建 bean 对象,并缓存到 DefaultSingletonBeanRegistry#singletonObjects 中
- 当我们的 Spring Bean 全部初始化完成之后,再进行 afterSingletonsInstantiated() 方法的回调
7.Spring Bean 销毁前阶段
方法回调
- DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
7.1 示例代码
新增 MyDestructionAwareBeanPostProcessor 实现 DestructionAwareBeanPostProcessor
覆盖 postProcessBeforeDestruction 销毁前的方法
public class MyDestructionAwareBeanPostProcessor implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && UserHolder.class.equals(bean.getClass())) {
UserHolder user = UserHolder.class.cast(bean);
user.setDescription("The user holder v9");
System.out.println("销毁前阶段 : postProcessBeforeDestruction() -> The user holder v9");
}
}
}
调用需要的执行 beanFactory.destroyBean("userHolder",userHolder);
销毁这个 bean 才会触发销毁前的过程。
/**
* Bean 完整生命周期
*/
public class BeanLifecycleDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//添加 CommonAnnotationBeanPostProcessor 触发 @PostConstruct
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
// 添加 DestructionAwareBeanPostProcessor 销毁前
beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
beanFactory.preInstantiateSingletons();
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
beanFactory.destroyBean("userHolder",userHolder);
System.out.println(userHolder);
}
}
执行结果:
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
初始化后阶段 : postProcessAfterInitialization() -> The user holder v7
初始化完成阶段 : afterSingletonsInstantiated() -> The user holder v8
销毁前阶段 : postProcessBeforeDestruction() -> The user holder v9
UserHolder{number=1, description='The user holder v9, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
7.2 源码调试
org.springframework.beans.factory.support.DisposableBeanAdapter#destroy
循环遍历 beanPostProcessors,执行 postProcessBeforeDestruction 方法
8.Spring Bean 销毁阶段
Bean 销毁(Destroy)
- @PreDestroy 标注方法
- 实现 DisposableBean 接口的 destroy() 方法
- 自定义销毁方法
8.1 示例方法
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, InitializingBean,SmartInitializingSingleton, DisposableBean {
...//省略掉其他重复代码
@PreDestroy
public void preDestroy(){
this.description = "The userHolder v10";
System.out.println("销毁阶段 : @PreDestroy -> The user holder v10");
}
@Override
public void destroy() throws Exception {
this.description = "The userHolder v11";
System.out.println("初始化阶段 : DisposableBean#destroy -> The user holder v11");
}
public void customDestroy(){
this.description = "The userHolder v12";
System.out.println("初始化阶段 : customDestroy -> The user holder v12");
}
}
bean-constructor-injection.xml 增加 destroy-method="customDestroy"
属性
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:/META-INF/dependency-lookup-context.xml"/>
<bean class="com.huajie.thinking.in.spring.bean.lifecycle.MyInstantiationAwareBeanPostProcess"/>
<bean id="userHolder" class="com.huajie.thinking.in.spring.bean.lifecycle.domain.UserHolder"
autowire="constructor" init-method="customInit" destroy-method="customDestroy">
<!--<property name="number" value="1"/>-->
<property name="description" value="The user holder" />
</bean>
</beans>
调用示例,注意 DestructionAwareBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 的添加顺序,因为 @PostConstruct、@PreDestroy 由 CommonAnnotationBeanPostProcessor 触发,但是 BeanPostProcessor 的添加是 FIFO 的模式,所以 DestructionAwareBeanPostProcessor 必须在之前进行添加。
/**
* Bean 完整生命周期
*/
public class BeanLifecycleDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//添加 DestructionAwareBeanPostProcessor 销毁前
beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
//添加 CommonAnnotationBeanPostProcessor 触发 @PostConstruct
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
beanFactory.preInstantiateSingletons();
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
beanFactory.destroyBean("userHolder",userHolder);
System.out.println(userHolder);
}
}
执行结果:
属性赋值前阶段 : postProcessProperties() -> The user holder v2
Disconnected from the target VM, address: '127.0.0.1:51595', transport: 'socket'
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
初始化后阶段 : postProcessAfterInitialization() -> The user holder v7
初始化完成阶段 : afterSingletonsInstantiated() -> The user holder v8
销毁前阶段 : postProcessBeforeDestruction() -> The user holder v9
销毁阶段 : @PreDestroy -> The user holder v10
初始化阶段 : DisposableBean#destroy -> The user holder v11
初始化阶段 : customDestroy -> The user holder v12
UserHolder{number=1, description='The userHolder v12, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
8.2 源码调试
DisposableBeanAdapter#destroy 242 行,可以看到有两个 beanPostProcessor,分别是我们添加的 DestructionAwareBeanPostProcessor、CommonAnnotationBeanPostProcessor
1.DestructionAwareBeanPostProcessor 执行销毁前的方法
2.CommonAnnotationBeanPostProcessor 触发 @PreDestroy 销毁方法
258 行,执行 DisposableBean#destroy 方法
273 行,执行我们自定义的方法 customDestroy
9.Spring Bean 垃圾收集
Bean 垃圾回收
- 关闭 Spring 容器(应用上下文)
- 执行 GC
- Spring Bean 覆盖 finalize() 方法被回调
9.1 示例改造
UserHolder 覆盖 Object#finalize 方法,因为这个方法会在对象被 GC 的时候调用
public class UserHolder implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, EnvironmentAware, InitializingBean, SmartInitializingSingleton, DisposableBean {
...//省略重复代码
@Override
public void finalize() throws Throwable {
System.out.println(beanName + " 被垃圾回收");
}
}
调用示例中添加
- beanFactory.destroySingletons();//销毁掉所有单例对象,保证没有对象的强引用,导致无法 gc
- userHolder=null;//对象置为空
- System.gc(); //调用 Full gc
/**
* Bean 完整生命周期
*/
public class BeanLifecycleDemo {
public static void main(String[] args) throws InterruptedException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//添加 BeanpostBeanProcess 实现
beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcess());
//添加 DestructionAwareBeanPostProcessor 销毁前
beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
//添加 CommonAnnotationBeanPostProcessor 触发 @PostConstruct
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String[] locations = {"classpath:/META-INF/dependency-lookup-context.xml", "classpath:/META-INF/bean-constructor-injection.xml"};
int count = reader.loadBeanDefinitions(locations);
beanFactory.preInstantiateSingletons();
UserHolder userHolder = beanFactory.getBean("userHolder", UserHolder.class);
// beanFactory.destroyBean("userHolder",userHolder);
beanFactory.destroySingletons();
System.out.println(userHolder);
userHolder=null;
System.gc();
Thread.sleep(5000);
}
}
执行结果:
user用户对象初始化...
属性赋值前阶段 : postProcessProperties() -> The user holder v2
初始化前阶段 : postProcessBeforeInitialization() -> The user holder v3
初始化阶段 : @PostConstruct -> The user holder v4
初始化阶段 : afterPropertiesSet() -> The user holder v5
初始化阶段 : customInit() -> The user holder v6
初始化后阶段 : postProcessAfterInitialization() -> The user holder v7
初始化完成阶段 : afterSingletonsInstantiated() -> The user holder v8
销毁前阶段 : postProcessBeforeDestruction() -> The user holder v9
销毁阶段 : @PreDestroy -> The user holder v10
初始化阶段 : DisposableBean#destroy -> The user holder v11
初始化阶段 : customDestroy -> The user holder v12
user用户对象销毁...
UserHolder{number=1, description='The userHolder v12, user=SuperUser{address='null'}User{beanName='null', id=null, name='new-superUser v1', age=null, configFileReource=null, city=null, cities=null, lifeCities=null}}
userHolder 被垃圾回收
10.面试题
10.1 BeanPostProcessor 的使用场景有哪些?
BeanPostProcessor 提供 Spring Bean 初始化前和初始化后的生命周期回调,分别对应 postProcessBeforelnitialization 以及 pistProcessAfterInitialization 方法,允许对相关的 Bean 进行扩展,甚至是替换。
BeanPostProcessor 的子类 DestructionAwareBeanPostProcessor 提供销毁前的生命周期回调。
BeanPostProcessor 的子类 InstantiationAwareBeanPostProcessor 提供实例化前postProcessBeforeInstantiation,实例化后 postProcessAfterInstantiation,属性赋值前 postProcessProperties 的生命周期回调。
加分项:其中 ApplicationContext 相关的 Aware 回调也是基于 BeanPostProcessor 实现,即 ApplicationContextAwareProcessor。
10.2 BeanFactoryPostProcessor 与 BeanPostProcessor 的区别?
其实两者无法进行对比,BeanFactoryPostProcessor 是 Spring BeanFactory(实际是ConfigurableListableBeanFactory)的后置处理器,用于扩展 BeanFactory,或者通过 BeanFactory 进行依赖查找和依赖注入。
而 BeanPostProcessor 则是直接与 BeanFactory 关联,属于 N 对 1 的关系。
加分项:BeanFactoryPostProcessor 必须有 Spring ApplicationContext 执行,BeanFactory 无法直接与其交互。
10.3 BeanFactory 是怎样处理 Bean 生命周期?
BeanFactory 的默认实现为 DefaultListableBeanFactory ,其中 Bean 生命周期与方法映射如下:
-
BeanDefinition 注册阶段 - registerBeanDefinition
-
BeanDefinition 合并阶段 - getMergedBeanDefinition
-
Bean 实例化前阶段 - resolveBeforeInstantiation
-
Bean 实例化阶段 - createBeanInstance
-
Bean 实例化后阶段 - populateBean
-
Bean 属性赋值前阶段 - populateBean
-
Bean 属性赋值阶段 - populateBean
-
Bean Aware 接口回调阶段 - initializeBean
-
Bean 初始化前阶段 - initializeBean
-
Bean 初始化阶段 - initializeBean
-
Bean 初始化后阶段 - initializeBean
-
Bean 初始化完成阶段 - preInstantiateSingletons
-
Bean 销毁前阶段 - destroyBean
-
Bean 销毁阶段 - destroyBean
11.参考
- 极客时间-小马哥《小马哥讲Spring核心编程思想》