实践出真知:理解Spring Bean生命周期

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/programmer_at/article/details/82533396

Bean的生命周期,尤其是Bean从实例化到可以使用,过程较为复杂,所以建议自己coding一遍来加深理解。
该周期中涵盖了Spring Aware接口,Spring PostProcessor后置处理器等等,首次接触时可能会觉得晦涩难懂,结合应用场景更有助于理解。

生命周期

这里写图片描述

Spring Aware接口

org.springframework.beans.factory.Aware使得自定义Bean可以识别利用Spring容器的资源,比如,
- BeanNameAware.setBeanName(String),可以在Bean中得到它在IOC容器中的Bean的实例的名字。
- BeanFactoryAware.setBeanFactory(BeanFactory),可以在Bean中得到Bean所在的IOC容器,从而直接在Bean中使用IOC容器的服务。
- ApplicationContextAware.setApplicationContext(ApplicationContext),可以在Bean中得到Bean所在的应用上下文,从而直接在Bean中使用上下文的服务。
- MessageSourceAware,在Bean中可以得到消息源。
- ApplicationEventPublisherAware,在bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件。
- ResourceLoaderAware,在Bean中可以得到ResourceLoader,从而在bean中使用ResourceLoader加载外部对应的Resource资源。

如非必要,Spring官方不推荐自定义Bean实现Aware接口,这会增加代码与Spring 框架的耦合性。

Spring PostProcessor

BeanFactoryPostProcessor可以对bean的配置信息进行操作。结合Bean的生命周期,Spring IOC容器允许BeanFactoryPostProcessor读取配置信息并且能够在容器实例化任何其他bean之前改变配置信息。
BeanPostProcessor可以在Spring完成Bean实例化,配置,初始化之后实现自己的业务逻辑。

Spring Aware和PostProcessor都是提供了用户利用Spring IoC添加业务逻辑进一步定制Bean。

实例

这里写图片描述

public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, BeanClassLoaderAware,
        InitializingBean, DisposableBean {
    private String name;
    private String description;

    public MyBean() {
        System.out.println("**MyBean** construct.");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("**MyBean** BeanClassLoaderAware.setBeanClassLoader: " + classLoader.getClass());
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("**MyBean** BeanFactoryAware.setBeanFactory: " + beanFactory.getClass());
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("**MyBean** BeanNameAware.getBeanName: " + s);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("**MyBean** DisposableBean.destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("**MyBean** InitializingBean.afterPropertiesSet");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("**MyBean** ApplicationContextAware.setApplicationContext");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("**MyBean** MyBean finalized.");
    }

    @PostConstruct
    public void springPostConstruct() {
        System.out.println("**MyBean** @PostConstruct");
    }

    // xml文件中的init-method
    public void myInitMethod() {
        System.out.println("**MyBean** init-method");
    }

    @PreDestroy
    public void springPreDestroy() {
        System.out.println("**MyBean** @PreDestroy");
    }

    // xml文件中的destroy-method
    public void mydestroyMethod() {
        System.out.println("**MyBean** destory-method");
    }

    @Autowired
    public void setName(String name) {
        this.name = name;
        System.out.println("**MyBean** setName");
    }

    @Autowired
    public void setDescription(String description) {
        this.description = description;
        System.out.println("**MyBean** setDescription");
    }

    @Override
    public String toString() {
        return "MyBean{" +
                "name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("[MyBeanFactoryPostProcessor] constructor");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("[MyBeanFactoryPostProcessor] postProcessBeanFactory");
    }
}
public class MyBeanPostProcessor implements BeanPostProcessor {
    public MyBeanPostProcessor() {
        super();
        System.out.println("[MyBeanPostProcessor] constructor.");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("[MyBeanPostProcessor] postProcessBeforeInitialization: " + bean.getClass() + ": " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("[MyBeanPostProcessor] postProcessAfterInitialization: " + bean.getClass() + ": " + beanName);
        return bean;
    }
}
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("[MyInstantiationAwareBeanPostProcessor] constructor.");
    }

    // 接口方法、实例化Bean之前调用
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessBeforeInstantiation");
        return null;
    }

    // 接口方法、实例化Bean之前调用
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessAfterInstantiation");
        return true;
    }

    // 接口方法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessPropertyValues");
        // 注意返回结果,否则会无法正确Bean的属性
        return pvs;
    }
}
public class LifeCycleApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("lifecycle.xml");
        System.out.println("[Application] before get bean");
        MyBean bean = (MyBean) context.getBean("myBean");
        System.out.println("[Application] after get bean");
        System.out.println(bean);
        ((ClassPathXmlApplicationContext) context).registerShutdownHook();
    }
}

lifecycle.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.example.LifeCycle"/>
    <bean id="myBean" class="com.example.LifeCycle.MyBean" init-method="myInitMethod"
          destroy-method="mydestroyMethod">
    </bean>
    <bean class="com.example.LifeCycle.MyBeanPostProcessor"/>
    <bean class="com.example.LifeCycle.MyBeanFactoryPostProcessor"/>
    <bean class="com.example.LifeCycle.MyInstantiationAwareBeanPostProcessor"/>
</beans>

运行结果:

...
[MyBeanFactoryPostProcessor] constructor
...
MyBeanFactoryPostProcessor] postProcessBeanFactory
...
[MyBeanPostProcessor] constructor
...
[MyInstantiationAwareBeanPostProcessor] constructor
[MyInstantiationAwareBeanPostProcessor] constructor
**MyBean** construct.
...
[MyInstantiationAwareBeanPostProcessor] postProcessAfterInstantiation
[MyInstantiationAwareBeanPostProcessor] postProcessPropertyValues
...
*MyBean** setName
**MyBean** setDescription
**MyBean** BeanNameAware.getBeanName: myBean
**MyBean** BeanClassLoaderAware.setBeanClassLoader: class sun.misc.Launcher$AppClassLoader
**MyBean** BeanFactoryAware.setBeanFactory: class org.springframework.beans.factory.support.DefaultListableBeanFactory
**MyBean** ApplicationContextAware.setApplicationContext
[MyBeanPostProcessor] postProcessBeforeInitialization: class com.example.LifeCycle.MyBean: myBean
...
**MyBean** init-method
...
MyBean{name='Gigi', description='description'}
...
**MyBean** @PreDestroy
**MyBean** DisposableBean.destroy
**MyBean** destory-method

一些建议

不建议使用InitializingBean, DisposableBean,因为这个会增加代码与Spring框架的耦合性。
@PostConstruct,@PreDestroy是JavaX的标准,而非Java,Spring定义的注解,使用时应该注意。
将Bean从Spring IoC中移除之前需要释放持有的资源,建议在destroy-method中写释放资源的代码。

Ref:
1. https://www.concretepage.com/spring/spring-bean-life-cycle-tutorial
2. XXXAware讲解:https://www.baeldung.com/spring-bean-name-factory-aware
3. 后置处理器XXXPostProcessor讲解:
http://wiki.jikexueyuan.com/project/spring/bean-post-processors.html
https://www.jianshu.com/p/fb39f568cd5e

猜你喜欢

转载自blog.csdn.net/programmer_at/article/details/82533396