三种方式创建bean对象在springIOC容器中初始化、销毁阶段要调用的自定义方法

摘要:
创建springIOC容器完成…获取bean对象完成…关闭springIOC容器完成…汽车正在销毁…获取bean容器完成…关闭spring IOC容器已完成…从测试结果中,我们可以看到,对于原型模式,在获得bean对象并执行构造方法和属性赋值方法之后执行初始化。没有销毁过程,即使容器关闭,也不会被销毁。

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 {
    
    //初始化阶段调用的方法
    @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...

免责声明:文章转载自《三种方式创建bean对象在springIOC容器中初始化、销毁阶段要调用的自定义方法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇轩辕剑陆和外传平台版设置功能python的整数没有补码一说下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

配置Struts应用解读Struts应用的两大配置文件

1.引言 关于Struts项目,在以前的文章中我已经做过一些介绍,在此不再赘述。写本文,旨在从纯Struts应用配置的角度深入剖析Struts配置文件在Web应用中的所扮演的角色及其工作机制,以加深对Struts内幕的理解和认知。以期在实际开发项目中灵活应用,提高分析和解决实际问题的能力。 2.进入主题 Struts应用采用两个基于XML的配置文件来配置应用...

Qt中的QGLWidget简介

我对QGLWidget的理解就是,其从QWidget继承,额外实现了一些OpenGl的操作,归纳如下:1、使用QWidget的句柄winID返回的HWND对OpenGl的绘制设备进行初始化,用一个虚函数initializeGL()实现,用户可以重置这个函数。2、使用resizeGL(int width,int height);对GL的视口进行变换。同样是一...

Vuex 的项目实例1 项目初始化

1、通过 vue ui 命令打开可视化面板,创建新项目:vuex-demo 2、安装 vuex 依赖包 npm install vuex axios ant-design-vue -S 当然也可以使用可视化面板的依赖安装。 ant-design-vue 是UI组件库。 3、实现 Todos 基本布局(基于已有样式模板) main.js 文件: import...

Spring中FactoryBean的作用和实现原理

BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的。BeanFactory是Spring中Bean工厂的顶层接口,也是我们常说的SpringIOC容器,它定下了IOC容器的一些规范和常用方法并管理着Spring中所有的Bean,今天我们不讲它,我们看一下后面那个Facto...

spring集成Redis(单机、集群)

一、单机redis配置 1. 配置redis连接池 <bean id="jedisPoolConfig"class="redis.clients.jedis.JedisPoolConfig"> <!--控制一个pool可分配多少个jedis实例 --> <property name="maxTo...

TensorFlow 编程基础

1、TensorFlow   安装:https://www.cnblogs.com/pam-sh/p/12239387.html      https://www.cnblogs.com/pam-sh/p/12241942.html • 是一个开放源代码软件库,用于进行高性能数值计算• 借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、G...