Spring 可以管理 singleton 作用域的 Bean 的生命周期,Spring 可以精确的知道该 Bean 何时被创建、何时被初始化完成、容器何时准备销毁该 Bean 实例。Spring 无法管理 prototype 作用域的 Bean 。

1、Spring 管理 Bean 的生命周期行为的时机:

① 注入依赖关系之后
② 即将销毁 Bean 之前

2、依赖关系注入之后的行为


① 使用 init-method 属性在 Bean 全部属性设置结束后自动执行。

② 实现 InitializingBean 接口的 afterPropertiesSet() 方法。


<bean id="chinese" class="com.sunsharing.springDemo.model.impl.Chinese"
parent="person" init-method="init">
    <constructor-arg ref="steelAxe"/>
</bean>

配置中指定 init() 方法是一个生命周期的方法。

/**
 * Created by Hinbo on 2016/9/5.
 *
 */
public class Chinese implements Person, BeanNameAware, InitializingBean, ApplicationContextAware {

    private String beanName;
    private String name;
    private Axe axe;

    public Chinese(){}

    public Chinese(Axe axe){
        this.axe = axe;
    }

    public void setAxe(Axe axe){
        this.axe = axe;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void userAxe() {
        System.out.println(axe.chop());
    }

    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("setBeanName ...... ");
    }

    //在该 Bean 注入依赖关系之后调用该方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("正在执行初始化方法 afterPropertiesSet 。。。。。。");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("applicationContext afterPropertiesSet ...... ");
    }

    public void init(){
        System.out.println("正在执行初始化方法 init 。。。。。。");
    }

}

两种的生命周期方法几乎一样,但是实现 InitializingBean 接口的方式污染了代码,是一种侵入式的设计,建议直接使用第一种。如果同时使用两种方法,则会先使用 InitializingBean 接口中的方法,然后再执行 init-method 属性指定的方法。

执行结果:

spring容器启动后延迟执行_spring容器启动后延迟执行

3、Bean 销毁之前的行为


① 使用 destroy-method 属性,指定方法在该 Bean 销毁之前被自动执行,代码污染较小。

② 实现 DisposableBean 接口


singleton 作用域的 Bean 通常会随容器的关闭而销毁,在一个非 Web 应用的环境下可以在 JVM 里注册一个关闭钩子保证 Spring 容器关闭,且自动执行 singleton Bean 实例的回调方法。

<!-- 测试执行 Bean 销毁之前的行为 -->
<bean id="american" class="com.sunsharing.springDemo.model.impl.American"
    destroy-method="close">
</bean>

测试 Bean:

/**
 * Created by Hinbo on 2016/9/7.
 * 测试 Bean 销毁之前的行为
 */
public class American implements Person, DisposableBean {

    public American(){
        System.out.println("Spring 实例化。。。。。。");
    }
    public void userAxe() {
        System.out.println("American ......");
    }
    public void destroy() throws Exception {
        System.out.println("正在执行销毁之前的方法 destroy ......");
    }
    public void close(){
        System.out.println("正在执行销毁之前的方法 close ......");
    }
}

测试代码:

//创建 Spring 容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
Person person = ctx.getBean("chinese", Person.class);
American american = ctx.getBean("american", American.class);
//为 Spring 容器注册关闭的钩子
ctx.registerShutdownHook();

具体的与依赖注入之后的行为类似,建议使用 destroy-method 属性,代码污染小。

执行结果:

spring容器启动后延迟执行_spring容器启动后延迟执行_02

4、Spring 容器中 Bean 实例的生命周期流程:

创建实例 –> 注入依赖关系 –> 调用 afterPropertiesSet –> 调用 init-method 方法 –> 对外提供服务 –> 调用 destroy –> 调用 destroy-method 方法 –> 实例被销毁