• Spring Bean的生命周期详解


    Spring Bean的生命周期详解

      Spring IoC容器的本质目的就是为了管理Bean,对于Bean而言,在容器中存在其生命周期,它的初始化和销毁也需要一个过程,下面主要对其生命周期进行一个详解的解释。生命周期主要是为了了解Spring IoC容器初始化和销毁Bean的过程,通过下图即可以掌握Spring IoC容器初始化与销毁Bean的过程。

      

      通过上图,我们首先可以看到生命周期的步骤。

      1)如果Bean实现了接口 BeanNameAware 的 setBeanName 方法,那么它就会调用这个方法。

      2)如果Bean实现了接口 BeanfactoryAware 的 setBeanFactory 方法,那么它就会调用这个方法。

      3)如果Bean实现了接口 ApplicationContextAware 的 setApplicationContext方法,且 Spring IoC容器也必须是一个 ApplicationContext 接口的实现类,那么才会调用这个方法,否则是不调用的。

      4)如果 Bean 实现了接口 BeanPostProcessor 的 postProcessBeforeInitialization 方法,那么它就会调用这个方法。

      5)如果 Bean 实现了接口 BeanFactoryPostProcessor 的 afterPropertiesSet 方法,那么它就会调用这个方法。

      6)如果 Bean 自定义了初始化方法,它就会调用已定义的初始化方法。

      7)如果 Bean 实现了接口 BeanPostProcessor 的 postProcessAfterInitialization 方法,完成了这些调用,这时候Bean 就完成了初始化,那么Bean 就生存在 Spring IoC容器中,使用者就可以从中获取Bean的服务。

      

      当服务器正常关闭,或者遇到其他关闭Spring IoC容器的事件,它就会调用对应的方法完成Bean的销毁,其步骤如下:

      1)首先如果Bean实现了接口 DisposableBean 的 destory 方法,那么就会调用它。

      2)如果定义了自定义销毁方法,那么就会调用它。

      需要主要的是,上述的关于生命周期的接口,大部分都是针对单个Bean而言的,BeanPostProcessor 接口是针对所有Bean而言的,当一个Bean实现了上述的接口,只需要在Spring IoC容器中定义它就可以,Spring IoC容器会自动识别,并且按顺序执行,下面对BeanPostProcessor 接口进行实现和测试。

    BeanPostProcessor 的实现类,处理Spring IoC容器所有的Bean

    package com.cnblogs.demrystv.bean;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    public class BeanPostProcessorImpl implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "开始实例化");
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "实例化完成");
            return bean;
        }
    
    }

    测试生命周期

    package com.cnblogs.demrystv.pojo;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class JuiceMaker implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {
        private String beverageShop = null;
        private Source source = null;
    
        public String getBeverageShop() {
            return beverageShop;
        }
    
        public void setBeverageShop(String beverageShop) {
            this.beverageShop = beverageShop;
        }
    
        public Source getSource() {
            return source;
        }
    
        public void setSource(Source source) {
            this.source = source;
        }
    
        public String makeJuice() {
            String juice = "这是一杯由" + beverageShop + "饮品店,提供的" + source.getSize() + source.getSugar() + source.getFruit();
            return juice;
        }
    
        public void init() {
            System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义初始化方法");
        }
    
        public void destroy() {
            System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义销毁方法");
        }
    
        @Override
        public void setBeanName(String arg0) {
            System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanNameAware接口的setBeanName方法");
    
        }
    
        @Override
        public void setBeanFactory(BeanFactory arg0) throws BeansException {
            System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanFactoryAware接口的setBeanFactory方法");
        }
    
        @Override
        public void setApplicationContext(ApplicationContext arg0) throws BeansException {
            System.out.println(
                    "【" + this.getClass().getSimpleName() + "】调用ApplicationContextAware接口的setApplicationContext方法");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
        }
    }

    同时,为了使自定义的方法生效,应该在xml中声明自定义的初始化和销毁方法的Bean

      <!--BeanPostProcessor定义 -->
        <bean id="beanPostProcessor" class="com.cnblogs.demrystv.bean.BeanPostProcessorImpl" />
    
        <bean id="source" class="com.cnblogs.demrystv.pojo.Source">
            <property name="fruit" value="橙汁" />
            <property name="sugar" value="少糖" />
            <property name="size" value="大杯" />
        </bean>
    
        <bean id="juiceMaker" class="com.cnblogs.demrystv.pojo.JuiceMaker2"
            destroy-method="destroy" init-method="init">
            <property name="beverageShop" value="贡茶" />
            <property name="source" ref="source" />
        </bean>

    配置完成后,测试 Spring Bean的生命周期

    ClassPathXmlApplicationContext ctx = 
                    new ClassPathXmlApplicationContext("spring-cfg.xml");
            JuiceMaker juiceMaker = (JuiceMaker) ctx.getBean("juiceMaker");
            System.out.println(juiceMaker.makeJuice());
            ctx.close();

    运行它,可以得到下面的日志:

    【Source】对象source开始实例化
    【Source】对象source实例化完成
    【JuiceMaker】调用BeanNameAware接口的setBeanName 方法
    【JuiceMaker】调用BeanFactoryAware接口的setBeanFactory方法
    【JuiceMaker】调用ApplicationContextAware 接口的setApplicationContext方法
    【JuiceMaker】对象juicemaker开始实例化
    【JuiceMaker】调用InitializingBean 接口的afterpropertiesSet方法
    【JuiceMaker】执行自定义初始化方法
    【JuiceMaker】对象juiceMaker 实例化完成
     这是一杯由贡茶饮品店,提供的大杯少糖橙汁
    【JuiceMaker】调用DisposableBean接口的destory方法
    【JuiceMaker】执行自定义销毁方法

      从日志中就可以发现所有的生命周期的方法都已经被执行了,从打印的日志可以看到,BeanPostProcessor针对全部Bean,这样就可以利用生命周期来完成一些需要自定义的初始化和销毁Bean的行为。

  • 相关阅读:
    Sass 初级学习三
    Sass 初级学习二
    Sass 初级学习一
    数据库0,1和flase true的转换
    Mybatis逆向工程-mybatis generator
    码畜生活现状
    【抽五分钟】使用VuePress创建在线文档中心
    面经整理
    C#引用fo-dicom读取dicom文件异常
    windows10更新后, VMWare无法启动虚拟机: vmdb-14 pipe connection has been broken
  • 原文地址:https://www.cnblogs.com/Demrystv/p/9256351.html
Copyright © 2020-2023  润新知