三种方式定义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提供的接口,定义在初始化和销毁阶段要调用的方法
 */
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 implements InitializingBean, DisposableBean {
    
    //初始化阶段调用的方法
    @PostConstruct
    public void postConstruct() {
        System.out.println("postConstruct...");
    }

    //销毁阶段调用的方法
    @PreDestroy
    public void preDestroy() {
        System.out.println("preDestroy...");
    }

    ...
}

4. 那么,在同一个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...

猜你喜欢

转载自www.cnblogs.com/dubhlinn/p/10664402.html