天天看點

Spring bean 的初始化和銷毀的三種方式和執行順序

Spring 容器中的 Bean 是有生命周期的,spring 允許 Bean 在初始化完成後以及銷毀前執行特定的操作。 下面是常用的三種指定特定操作的方法:

  • 通過實作InitializingBean/DisposableBean 接口來定制初始化之後/銷毀之前的操作方法; 
  • 通過<bean> 元素的init-method/destroy-method屬性指定初始化之後 /銷毀之前調用的操作方法;
  • 在指定方法上加上@PostConstruct或@PreDestroy注解來制定該方法是在初始化之後還是銷毀之前調用。

這幾種配置方式,執行順序是怎樣的呢?我們通過例子來研究下:

Bean的列子類:InitBeanAndDestroyBean.java

package com.chenfeng.xiaolyuh.entity;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class InitBeanAndDestroyBean implements InitializingBean, DisposableBean {
  public String say() {
    return "Hello!" + this.getClass().getName();
  }

  public InitBeanAndDestroyBean() {
    System.out.println("執行InitBeanAndDestroyBean構造方法");
  }

  @Override
  public void destroy() throws Exception {
    System.out.println("接口-執行InitBeanAndDestroyBeanTest:destroy方法");
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    System.out.println("接口-執行InitBeanAndDestroyBeanTest:afterPropertiesSet方法");
  }

  @PostConstruct
  public void postConstructstroy() {
    System.out.println("注解-執行InitBeanAndDestroyBeanTest:preDestroy方法");
  }

  @PreDestroy
  public void preDestroy() {
    System.out.println("注解--執行InitBeanAndDestroyBeanTest:preDestroy方法");
  }

  public void initMethod() {
    System.out.println("XML配置-執行InitBeanAndDestroyBeanTest:init-method方法");
  }

  public void destroyMethod() {
    System.out.println("XML配置-執行InitBeanAndDestroyBeanTest:destroy-method方法");
  }
}      

Spring配置類MyConfig.java

@Configuration // 聲明成配置檔案
@ComponentScan("com.chenfeng.xiaolyuh") // 掃描包
public class MyConfig {
  
  // 測試Bean的幾種初始化和銷毀方式,和執行順序
  @Bean(initMethod="initMethod", destroyMethod="destroyMethod")
  public InitBeanAndDestroyBean initBeanAndDestroyBean() {
    return new InitBeanAndDestroyBean();
  }
}      

測試類SpringIocTest.java

public class SpringIocTest {
    // 使用容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class, CatEntity.class);

    @Test
    public void contextTest() {
        // 測試Bean的三種初始化、銷毀方式和執行順序
        System.out.println(context.getBean(InitBeanAndDestroyBean.class));
    }
    
    @After
    public void closeContext() {
        context.close();
    }

}      

列印結果:

三月 10, 2017 1:47:02 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh

資訊: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3b22cdd0: startup date [Fri Mar 10 13:47:02 CST 2017]; root of context hierarchy

執行InitBeanAndDestroyBean構造方法

注解-執行InitBeanAndDestroyBeanTest:preDestroy方法

接口-執行InitBeanAndDestroyBeanTest:afterPropertiesSet方法

XML配置-執行InitBeanAndDestroyBeanTest:init-method方法

三月 10, 2017 1:47:02 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose

資訊: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3b22cdd0: startup date [Fri Mar 10 13:47:02 CST 2017]; root of context hierarchy

注解--執行InitBeanAndDestroyBeanTest:preDestroy方法

接口-執行InitBeanAndDestroyBeanTest:destroy方法

XML配置-執行InitBeanAndDestroyBeanTest:destroy-method方法

  • Bean在執行個體化的過程中:Constructor > @PostConstruct >InitializingBean > init-method
  • Bean在銷毀的過程中:@PreDestroy > DisposableBean > destroy-method