目录

Spring Bean的生命周期

Spring容器既Application或者WebApplication会在管理Bean的时候;为了尽可能的把自己内部的东西机制暴露出来给用户使用,所以在Bean创建的过程中加了很多机制,通过所谓的"处理器"Processor暴露出来,然后处理器都有自己的顺序,我们需要做的就是定义好处理器的逻辑,然后注册到Sprinhg容器中,Spring就会调用了。下面就是Spring管理Bean的生命周期图。

Spring Framework核心概念之Bean生命周期管理-LMLPHP

Spring Framework核心概念之Bean生命周期管理-LMLPHP

下面这张图描述的更为详细。

Spring Framework核心概念之Bean生命周期管理-LMLPHP

相关接口的分类

对于上面图看不懂不要着急因为你并不认识与生命周期相关的接口。Spring生命周期你可以理解为四个等级;每个等级中都用有相应的接口,实现其中某个接口或者将实现类注入到Sprng容器,容器就会在相应的时机调用其方法。详细信息可看下面的一个表格。

  • 工厂后处理器接口方法
  • 容器级生命周期接口方法
  • Bean级生命周期接口方法
  • Bean本身方法

测试SpringBean生命周期的Demo程序

本测试程序来自https://www.cnblogs.com/zrtqsk/p/3735273.html 我在这里说一下测试程序是如何测试SpringBean的生命周期的。首先将一个工厂后处理器 BeanFactoryPostProcessor接口实现注入容器,再将容器后处理器InstantiationAwareBeanPostProcessorBeanPostProcessor注入容器,又在自定义Person实现了Bean级后处理器BeanNameAwareBeanFactoryAwareInitializingBeanDiposableBean接口的相关方法,最后就是在自定义的Person类中实现了其本身的init()方法和destroy()方法。

  • 自定义Person类
public class Person implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean {

    private String name;
    private String address;
    private int phone;

    private BeanFactory beanFactory;
    private String beanName;

    public Person() {
        System.out.println("【构造器】调用Person的构造器实例化");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("【注入属性】注入属性name");
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        System.out.println("【注入属性】注入属性address");
        this.address = address;
    }

    public int getPhone() {
        return phone;
    }

    public void setPhone(int phone) {
        System.out.println("【注入属性】注入属性phone");
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Person [address=" + address + ", name=" + name + ", phone="
                + phone + "]";
    }

    // 这是BeanFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory arg0) throws BeansException {
        System.out
                .println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
        this.beanFactory = arg0;
    }

    // 这是BeanNameAware接口方法
    @Override
    public void setBeanName(String arg0) {
        System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
        this.beanName = arg0;
    }

    // 这是InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out
                .println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
    }

    // 这是DiposibleBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
    }

    // 通过<bean>的init-method属性指定的初始化方法
    public void myInit() {
        System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
    }

    // 通过<bean>的destroy-method属性指定的初始化方法
    public void myDestory() {
        System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
    }
}
  • MyBeanPostProcessor (实现容器级别后置处理器)
public class MyBeanPostProcessor implements BeanPostProcessor {
    public MyBeanPostProcessor() {
        super();
        System.out.println("这是BeanPostProcessor实现类构造器!!");
        // TODO Auto-generated constructor stub
    }

    @Override
    public Object postProcessAfterInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out
                .println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
        return arg0;
    }

    @Override
    public Object postProcessBeforeInitialization(Object arg0, String arg1)
            throws BeansException {
        System.out
                .println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
        return arg0;
    }
}
  • MyInstantiationAwareBeanPostProcessor(实现容器级别后置处理器)
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out
                .println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
    }

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

    // 接口方法、实例化Bean之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out
                .println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
        return bean;
    }

    // 接口方法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                    PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        System.out
                .println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
        return pvs;
    }
}
  • MyBeanFactoryPostProcessor (实现容器级别后置处理器)
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        System.out
                .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
        BeanDefinition bd = arg0.getBeanDefinition("person");
        bd.getPropertyValues().addPropertyValue("phone", "110");
    }
}
  • 配置Spring的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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <bean id="beanPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanPostProcessor">
    </bean>

    <bean id="instantiationAwareBeanPostProcessor"
          class="com.jimisun.learnspringboot.web.MyInstantiationAwareBeanPostProcessor">
    </bean>

    <bean id="beanFactoryPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanFactoryPostProcessor">
    </bean>

    <bean id="person" class="com.jimisun.learnspringboot.web.Person" init-method="myInit"
          destroy-method="myDestory" scope="singleton" p:name="张三" p:address="广州"
          p:phone="15900000000"/>

</beans>
  • Main方法执行测试
public class Main {
    public static void main(String[] args) {

        System.out.println("现在开始初始化容器");

        ApplicationContext factory = new ClassPathXmlApplicationContext("bens.xml");
        System.out.println("容器初始化成功");
        //得到Preson,并使用
        Person person = factory.getBean("person",Person.class);
        System.out.println(person);

        System.out.println("现在开始关闭容器!");
        ((ClassPathXmlApplicationContext)factory).registerShutdownHook();
    }

}
  • 测试结果(我对Main方法执行结果做了格式化,方便参照)

Spring Framework核心概念之Bean生命周期管理-LMLPHP

LOGGER测试:现在开始初始化容器
    【工厂构造】这是BeanFactoryPostProcessor实现类构造器!!
    【工厂方法】BeanFactoryPostProcessor调用postProcessBeanFactory方法
        【容器构造】这是BeanPostProcessor实现类构造器!!
        【容器构造】这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
        【容器方法】InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
            【类构造】调用Person的构造器实例化
        【容器方法】InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
                【类注入属性】注入属性address
                【类注入属性】注入属性name
                【类注入属性】注入属性phone
                【Bean方法:BeanNameAware接口】调用BeanNameAware.setBeanName()
                【Bean方法:BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
            【容器方法】BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!
                【Bean方法:InitializingBean接口】调用InitializingBean.afterPropertiesSet()
                【自身方法:init-method】调用<bean>的init-method属性指定的初始化方法
            【容器方法】BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!
        【容器方法】InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
LOGGER测试:容器初始化成功
    Person [address=广州, name=张三, phone=110]
LOGGER测试:现在开始关闭容器!
                【Bean级别:DiposibleBean接口】调用DiposibleBean.destory()
                【自身方法:destroy-method】调用<bean>的destroy-method属性指定的初始化方法

将Demo代码的执行结果与上述表中的执行时机进行对比,看看执行时机是否正确,

小结

理解透彻Spring Bean的生命周期对开发中可以解决比较棘手的问题,对于深入学习Spring Framework框架这是必须要掌握的知识,所以可以多看两遍。

12-11 01:41