夯实Spring系列|第十四章:Spring Bean 生命周期-下篇

夯实Spring系列|第十四章:Spring Bean 生命周期-下篇

本章说明

本文是 Spring Bean 生命周期系列的最后一篇,会对 Spring Bean 初始化阶段以及后面的销毁阶段进行分析和讨论。Aware 回调源码其实是在 initializeBean 方法中 (初始化 Bean 阶段),所以也可以当成是 Spring Bean 初始化阶段。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pdvWTz6R-1588321832427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200429125110856.png)]

1.项目环境

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 阶段。
在这里插入图片描述
继续往下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HfDrzgw6-1588321832432)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200430091207719.png)]
源码位置 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 源码分析

从源码可以很清晰的看到 初始化前 -> 初始化 -> 初始化后 三个阶段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kmvd9QAI-1588321832434)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200430161813049.png)]
过程相对简单,这里就不一 一截图演示了,可对照源码位置打上断点进行调试:

  • 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 方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9Uf69ls-1588321832436)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200501135005300.png)]

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 销毁方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PwpbVJ3z-1588321832437)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200501144444266.png)]
258 行,执行 DisposableBean#destroy 方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KljkXnZT-1588321832438)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200501144748023.png)]
273 行,执行我们自定义的方法 customDestroy
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCdEtMbn-1588321832438)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200501144907529.png)]

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核心编程思想》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值