三种方式创建bean对象在springIOC容器中初始化、销毁阶段要调用的自定义方法
1. 使用@Bean注解定义initMethod和destroyMethod
所谓initMethod和destroyMethod,是指在springIOC容器中,对于bean对象执行到初始化阶段和销毁阶段所调用的方法,其并不是初始化方法和销毁方法本身。
对于单例模式,initMethod会在创建容器时,构造方法、属性赋值方法完成之后调用,destroyMethod会在关闭容器之后调用;
对于原型模式,initMethod会在每次获取bean对象时,构造方法、属性赋值方法完成之后调用,而destroyMethod则不会调用,换句话说,对于多实例bean,springIOC容器只负责创建,不负责销毁。
/** * 使用@Bean注解的方式定义initMethod和destroyMethod * initMethod方法: * 是springIOC容器执行到初始化bean对象阶段时调用的方法,并不是初始化bean对象方法本身 * 对于单实例模式,是在创建容器之后执行,只执行一次 * 对于多实例模式,是在获取bean对象时执行,每获取一次,则执行一次 * destroyMethod方法: * 是springIOC容器执行到销毁bean对象阶段时调用的方法,并不是销毁bean对象方法本身 * 对于单例模式,是在关闭容器之前执行 * 对于多实例模式,ICO容器不负责销毁对象,因此销毁方法也不负责执行 */ @Configuration public class LifeBeanConfig { /** * 单例模式注册Car * bean初始化阶段调用onInit方法 * bean销毁阶段调用onDestroy方法 */ @Bean(value = "singleCar", initMethod = "onInit", destroyMethod = "onDestroy") @Scope(value = SCOPE_SINGLETON) public Car singleCar() { //调用无参构造器创建Car对象 Car car = new Car(); //设置属性 car.setMake("BMW X5"); car.setPrice(600000); //返回Car对象 return car; } /** * 多例模式注册Car * bean初始化阶段调用onInit方法 * bean销毁阶段调用onDestroy方法 */ @Bean(value = "multiCar", initMethod = "onInit", destroyMethod = "onDestroy") @Scope(value = SCOPE_PROTOTYPE) public Car multiCar() { //调用无参构造器创建Car对象 Car car = new Car(); //设置属性 car.setMake("BMW X5"); car.setPrice(600000); //返回Car对象 return car; } }
测试单例模式
/** * 测试使用单实例@Bean注解定义初始化和销毁阶段调用的方法 */ @Test public void test1() { //创建springIOC容器 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class); System.out.println("创建springIOC容器完成..."); //从容器中获取bean对象 Car car = (Car) applicationContext.getBean("singleCar"); System.out.println("获取bean对象完成..."); //关闭springIOC容器 ((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook(); System.out.println("关闭springIOC容器完成..."); }
测试结果
正在调用Car的无参构造方法……
正在为Car的make属性赋值……
正在为Car的price属性赋值……
car正在初始化……
创建springIOC容器完成...
获取bean对象完成...
关闭springIOC容器完成...
car正在销毁……
从测试结果看出,对于单例模式,初始化是在创建springIOC容器时,在执行完构造方法和属性赋值方法之后执行的,销毁是在执行关闭容器方法之后、容器真正关闭之前执行的
测试原型模式
/** * 测试使用多实例@Bean注解定义初始化和销毁阶段调用的方法 */ @Test public void test2() { //创建springIOC容器 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class); System.out.println("创建springIOC容器完成..."); //从容器中获取bean对象 Car car = (Car) applicationContext.getBean("multiCar"); System.out.println("获取bean对象完成..."); //关闭springIOC容器 ((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook(); System.out.println("关闭springIOC容器完成..."); }
测试结果
创建springIOC容器完成...
正在调用Car的无参构造方法……
正在为Car的make属性赋值……
正在为Car的price属性赋值……
car正在初始化……
获取bean对象完成...
关闭springIOC容器完成...
从测试结果可以看出,对于原型模式,初始化是在获取bean对象时,在执行完构造方法和属性赋值方法之后执行的,没有销毁过程,即使容器关闭也并没有销毁。
2. 通过实现spring提供的接口,定义初始化阶段和销毁阶段需要执行的方法
在bean类上实现InitializingBean,其实现方法afterPropertiesSet会在初始化阶段完成了构造方法和属性赋值之后被执行,相当于上述initMethod;
同理,在bean类上实现DisposableBean接口,其实现方法destroy为在销毁阶段关闭了容器之后被执行,相当于上述destroyMethod。import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; /** * bean类 * 通过实现spring提供的接口,定义在初始化和销毁阶段要调用的方法 */
@Component public class Bus implements InitializingBean, DisposableBean { /** * 初始化阶段,在完成属性赋值方法之后调用的方法 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { System.out.println("正在对bus对象进行初始化..."); } /** * 销毁阶段,在关闭容器之后调用的方法 * @throws Exception */ @Override public void destroy() throws Exception { System.out.println("正在对bus对象进行销毁..."); } ... }
3. 通过加JSR-250规范的注解,定义初始化阶段和销毁阶段需要执行的方法
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * bean类 * 通过加JSR-250注解,定义在初始化和销毁阶段要调用的方法 */ public class Bus { //初始化阶段调用的方法 @PostConstruct public void postConstruct() { System.out.println("postConstruct..."); } //销毁阶段调用的方法 @PreDestroy public void preDestroy() { System.out.println("preDestroy..."); } ... }
那么,在同一个bean类上定义initMethod/destroyMethod方法、实现InitializingBean/Disposable接口、加PostContruct/PreDestroy注解,这三组方法的执行顺序如何?经测试,JSR-250注解先执行,spring接口第二个执行,bean注解声明的initMethod/destroyMethod最后执行。
package cn.monolog.entity; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * bean类 * 分别通过三种方式定义初始化阶段和销毁阶段要调用的方法 */ public class Bus implements InitializingBean, DisposableBean { //初始化阶段调用的方法,需要在配置类的@Bean注解中将该方法定义为initMethod public void onInit() { System.out.println("initMethod..."); } //销毁阶段调用的方法,需要在配置类的@Bean注解中将该方法定义为destroyMethod public void onDestroy() { System.out.println("destroyMethod..."); } /** * 初始化阶段,在完成属性赋值方法之后调用的方法 * @throws Exception */ @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean..."); } /** * 销毁阶段,在关闭容器之后调用的方法 * @throws Exception */ @Override public void destroy() throws Exception { System.out.println("DisposableBean..."); } //初始化阶段调用的方法 @PostConstruct public void postConstruct() { System.out.println("postConstruct..."); } //销毁阶段调用的方法 @PreDestroy public void preDestroy() { System.out.println("preDestroy..."); } ... }
@Test public void test() { //创建springIOC容器 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeBeanConfig.class); System.out.println("创建springIOC容器完成..."); //关闭springIOC容器 ((AnnotationConfigApplicationContext)applicationContext).registerShutdownHook(); System.out.println("关闭springIOC容器完成..."); }
测试结果:
正在调用bus的无参构造方法...
正在对bus的make属性进行赋值...
正在对bus的price属性进行赋值...
postConstruct...
InitializingBean...
initMethod...
创建springIOC容器完成...
关闭springIOC容器完成...
preDestroy...
DisposableBean...
destroyMethod...