zoukankan      html  css  js  c++  java
  • 三种方式创建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 {
        
        //初始化阶段调用的方法
        @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...

  • 相关阅读:
    "use strict"
    jquery.is()
    $.proxy
    windows检测文件夹是否更新.bat脚本 windows循环检查文件夹
    linux下串口多线程通信 ,多串口收发数据错乱问题解决办法
    linux串口配置详解
    linux socket 程序被ctrl+c或者异常终止,提示:bind error:Address already in use,解决办法
    linux下包含自定义.c文件 调用报错未定义解决办法
    linux下对一个文件写完马上读取,读到空白
    linux 下socket通信,client断开service退出解决办法
  • 原文地址:https://www.cnblogs.com/dubhlinn/p/10664402.html
Copyright © 2011-2022 走看看