相关推荐recommended
SpringBoot:Bean生命周期自定义初始化和销毁
作者:mmseoamin日期:2024-02-04

SpringBoot:Bean生命周期自定义初始化和销毁,在这里插入图片描述,第1张


🏡浩泽学编程:个人主页

 🔥 推荐专栏:《深入浅出SpringBoot》《java项目分享》
              《RabbitMQ》《Spring》《SpringMVC》
🛸学无止境,不骄不躁,知行合一

文章目录

  • 前言
  • 一、@Bean注解指定初始化和销毁方法
  • 二、实现InitializingBean接口和DisposableBean接口
  • 三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解
  • 四、BeanPostProcessor接口
  • 总结

    前言

    上篇文章详细讲诉了Bean的生命周期和作用域,在生命周期中提到了如何自定义初始化Bean,可能很多人不知道如何自定义初始化,这里详细补充讲解一下:使用@Bean注解指定初始化和销毁方法、实现InitializingBean接口和DisposableBean接口自定义初始化和销毁、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解、使用BeanPostProcessor接口。


    一、@Bean注解指定初始化和销毁方法

    • 创建BeanTest类,自定义初始化方法和销毁方法。
    • 在@Bean注解的参数中指定BeanTest自定义的初始化和销毁方法:
    • 销毁方法只有在IOC容器关闭的时候才调用。

    代码如下:

    /**
     * @Version: 1.0.0
     * @Author: Dragon_王
     * @ClassName: dog
     * @Description: TODO描述
     * @Date: 2024/1/21 22:55
     */
    public class BeanTest {
        public BeanTest(){
            System.out.println("BeanTest被创建");
        }
        public void init(){
            System.out.println("BeanTest被初始化");
        }
        public void destory(){
            System.out.println("BeanTest被销毁");
        }
    }
    /**
     * @Version: 1.0.0
     * @Author: Dragon_王
     * @ClassName: MyConfig
     * @Description: TODO描述
     * @Date: 2024/1/21 22:59
     */
    @Configuration
    @ComponentScan(("com.dragon.restart1"))
    public class MyConfig {
        @Bean(initMethod = "init",destroyMethod = "destory")
        public BeanTest beanTest(){
            return new BeanTest();
        }
    }
    //测试代码
    AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext(MyConfig.class);
    System.out.println("IoC容器创建完成");
    

    SpringBoot:Bean生命周期自定义初始化和销毁,在这里插入图片描述,第2张

    • 可以看到调用的是自定义的方法,这里解释一下,测试时,运行完代码块程序就结束了,所哟IoC容器就被关闭,所以调用了IoC销毁方法。同时可以看到初始化方法在对象创建完成后调用。
    • 当组件的作用域为单例时在容器启动时即创建对象,而当作用域为原型(PROTOTYPE)时在每次获取对象的时候才创建对象。并且当作用域为原型(PROTOTYPE)时,IOC容器只负责创建Bean但不会管理Bean,所以IOC容器不会调用销毁方法。

      二、实现InitializingBean接口和DisposableBean接口

      看一下两接口的方法:

      public interface InitializingBean {
      	/**
      	 * Invoked by the containing {@code BeanFactory} after it has set all bean properties
      	 * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
      	 * 

      This method allows the bean instance to perform validation of its overall * configuration and final initialization when all bean properties have been set. * @throws Exception in the event of misconfiguration (such as failure to set an * essential property) or if initialization fails for any other reason * Bean都装配完成后执行初始化 */ void afterPropertiesSet() throws Exception; } ==================================================================== public interface DisposableBean { /** * Invoked by the containing {@code BeanFactory} on destruction of a bean. * @throws Exception in case of shutdown errors. Exceptions will get logged * but not rethrown to allow other beans to release their resources as well. */ void destroy() throws Exception; }

      代码如下:

      /**
       * @Version: 1.0.0
       * @Author: Dragon_王
       * @ClassName: BeanTest1
       * @Description: TODO描述
       * @Date: 2024/1/21 23:25
       */
      public class BeanTest1 implements InitializingBean, DisposableBean {
          @Override
          public void destroy() throws Exception {
              System.out.println("BeanTest1销毁");
          }
          @Override
          public void afterPropertiesSet() throws Exception {
              System.out.println("BeanTest1初始化");
          }
          public BeanTest1() {
              System.out.println("BeanTest1被创建");
          }
      }
      =========================
      @Configuration
      @ComponentScan(("com.dragon.restart1"))
      public class MyConfig {
       @Bean
          public BeanTest1 beanTest1(){
              return new BeanTest1();
          }
      }
      

      SpringBoot:Bean生命周期自定义初始化和销毁,在这里插入图片描述,第3张

      三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解

      • 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。
      • 被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
      • 被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

      代码如下:

      /**
       * @Version: 1.0.0
       * @Author: Dragon_王
       * @ClassName: BeanTest2
       * @Description: TODO描述
       * @Date: 2024/1/21 23:32
       */
      public class BeanTest2 {
          public BeanTest2(){
              System.out.println("BeanTest2被创建");
          }
          @PostConstruct
          public void init(){
              System.out.println("BeanTest2被初始化");
          }
          @PreDestroy
          public void destory(){
              System.out.println("BeanTest2被销毁");
          }
      }
      ========================
      //
      @Configuration
      @ComponentScan(("com.dragon.restart1"))
      public class MyConfig {
       @Bean
          public BeanTest2 beanTest2(){
              return new BeanTest2();
          }
      }
      

      SpringBoot:Bean生命周期自定义初始化和销毁,在这里插入图片描述,第4张

      四、BeanPostProcessor接口

      BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。

      BeanPostProcessor的源码如下:

      public interface BeanPostProcessor {
      	/**
      	 * Apply this BeanPostProcessor to the given new bean instance before any bean
      	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
      	 * or a custom init-method). The bean will already be populated with property values.
      	 * The returned bean instance may be a wrapper around the original.
      	 * 

      The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ @Nullable //bean初始化方法调用前被调用 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * Apply this BeanPostProcessor to the given new bean instance after any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. *

      In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. *

      This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. *

      The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ @Nullable //bean初始化方法调用后被调用 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }

      代码如下:

      /**
       * @Version: 1.0.0
       * @Author: Dragon_王
       * @ClassName: MyBeanPostProcess
       * @Description: TODO描述
       * @Date: 2024/1/21 23:40
       */
      @Component
      public class MyBeanPostProcess implements BeanPostProcessor {
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
              return bean;
          }
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
              return bean;
          }
      }
      ============================
      @Configuration
      @ComponentScan(("com.dragon.restart1"))
      public class MyConfig {
          @Bean
          public BeanTest1 beanTest1(){
              return new BeanTest1();
          }
          @Bean
          public BeanTest2 beanTest2(){
              return new BeanTest2();
          }
      }
      

      运行结果如下:

      BeanTest1被创建
      postProcessBeforeInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
      BeanTest1初始化
      postProcessAfterInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
      BeanTest2被创建
      postProcessBeforeInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
      BeanTest2被初始化
      postProcessAfterInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
      IoC容器创建完成
      BeanTest2被销毁
      BeanTest1销毁
      

      通过上述运行结果可以发现使用BeanPostProcessor的运行顺序为:

      IOC容器实例化Bean---->调用BeanPostProcessor的postProcessBeforeInitialization方法---->调用bean实例的初始化方法---->调用BeanPostProcessor的postProcessAfterInitialization方法。


      总结

      以上就是Bean生命周期自定义初始化和销毁的讲解。