zoukankan      html  css  js  c++  java
  • Spring bean 生命周期验证

    一、从源码注释看bean生命周期

    从JDK源码注释上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为:

    1.BeanNameAware setBeanName 设置bean名称
    2.BeanClassLoaderAware setBeanClassLoader 设置bean类加载器
    3.BeanFactoryAware setBeanFactory 设置bean工厂
    4.EnvironmentAware setEnvironment 设置环境:profiles+properties
    5.EmbeddedValueResolverAware setEmbeddedValueResolver 设置嵌入式值解析器
    6.ResourceLoaderAware setResourceLoader 设置资源载入器,只适用于在应用程序上下文中运行
    7.ApplicationEventPublisherAware setApplicationEventPublisher注入应用事件发布器ApplicationEventPublisher
    8.MessageSourceAware setMessageSource 设置国际化支持
    9.ApplicationContextAware setApplicationContext 设置应用上下文
    10.ServletContextAware setServletContext 设置servlet上下文
    11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
    12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
    13.a custom init-method definition 执行自定义初始化方法
    14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法

    销毁顺序:
    1.DestructionAwareBeanPostProcessors postProcessBeforeDestruction 销毁处理器的前置方法
    2.DisposableBean destroy Bean销毁回调方法
    3.a custom destroy-method definition 用户自定义销毁方法

    当然这里面不是所有方法都走一遍,核心方法流程图如下图:

    二、测试验证

    2.1分析原理

    前面说的17个步骤都可以测试,我们选取其中的8个步骤进行测试如下:

    初始化流程

    1.BeanNameAware setBeanName 设置bean名称
    3.BeanFactoryAware setBeanFactory 设置bean工厂
    11.BeanPostProcessors postProcessBeforeInitialization 执行bean处理器前置方法
    12.InitializingBean afterPropertiesSet 执行初始化Bean设置完属性后置方法
    13.a custom init-method definition 执行自定义初始化方法
    14.BeanPostProcessors postProcessAfterInitialization 执行bean处理器后置方法

    销毁流程

    2.DisposableBean destroy Bean销毁回调方法
    3.a custom destroy-method definition 用户自定义销毁方法

     2.2 代码清单

     1.构建一个Person类,实现BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean接口。

     1 package spring.ioc;
     2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.beans.factory.BeanFactory;
     5 import org.springframework.beans.factory.BeanFactoryAware;
     6 import org.springframework.beans.factory.BeanNameAware;
     7 import org.springframework.beans.factory.DisposableBean;
     8 import org.springframework.beans.factory.InitializingBean;
     9 
    10 public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    11     
    12     private String name;
    13     
    14     private String mobile;
    15      
    16     public Person() {
    17         super();
    18         System.out.println("[构造器] 调用Person的构造器实例化");
    19     }
    20 
    21     public String getName() {
    22         return name;
    23     }
    24 
    25     public void setName(String name) {
    26         System.out.println("[属性注入] name="+name);
    27         this.name = name;
    28     }
    29 
    30     public String getMobile() {
    31         return mobile;
    32     }
    33 
    34     public void setMobile(String mobile) {
    35         System.out.println("[属性注入] mobile="+mobile);
    36         this.mobile = mobile;
    37     }
    38 
    39     @Override
    40     public void destroy() throws Exception {
    41         System.out.println("[接口DisposableBean.destroy() ]");
    42     }
    43 
    44     @Override
    45     public void afterPropertiesSet() throws Exception {
    46         System.out.println("[接口InitializingBean.afterPropertiesSet() ]");
    47     }
    48 
    49     @Override
    50     public void setBeanName(String name) {
    51         System.out.println("[接口BeanNameAware.setBeanName() ]");
    52     }
    53 
    54     @Override
    55     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    56         System.out.println("[接口BeanFactoryAware.setBeanFactory() ]");
    57     }
    58 
    59     public void myInit(){
    60         System.out.println("[init-method]调用<bean>的init-method属性指定的初始化方法");
    61     }
    62     
    63     public void myDestory() {
    64         System.out.println("[destroy-method]调用<bean>的destroy-method属性指定的销毁方法");
    65     }
    66 
    67 }

    2.自定义工厂后处理器,复写postProcessBeanFactory方法,获取bean定义后添加属性mobile=110

     1 package spring.ioc;
     2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.beans.factory.config.BeanDefinition;
     5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
     6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
     7 
     8 /**
     9  * 
    10  * @ClassName:MyBeanFactoryPostProcessor
    11  * @Description:自定义工厂后处理器
    12  * @author diandian.zhang
    13  * @date 2017年10月25日下午7:14:09
    14  */
    15 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    16 
    17     public MyBeanFactoryPostProcessor() {
    18         super();
    19         System.out.println("[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor实现类构造器!!");
    20     }
    21 
    22     @Override
    23     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
    24             throws BeansException {
    25         System.out.println("[MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor.postProcessBeanFactory()获取bean定义后添加属性mobile=110");
    26         BeanDefinition bd = arg0.getBeanDefinition("person");
    27         bd.getPropertyValues().addPropertyValue("mobile", "110");
    28     }
    29 
    30 }

    3.自定义Bean后处理器,复写postProcessBeforeInitialization和postProcessAfterInitialization2个方法,分别对应初始化前后时的操作。

     1 package spring.ioc;
     2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.beans.factory.config.BeanPostProcessor;
     5 
     6 /**
     7  * 
     8  * @ClassName:MyBeanPostProcessor
     9  * @Description:自定义Bean后处理器
    10  * @author diandian.zhang
    11  * @date 2017年10月25日下午7:03:53
    12  */
    13 public class MyBeanPostProcessor implements BeanPostProcessor {
    14 
    15     public MyBeanPostProcessor() {
    16         super();
    17         System.out.println("这是BeanPostProcessor实现类构造器!!");
    18     }
    19 
    20     /**
    21      * 
    22      * @Description 初始化前,处理器
    23      * @param bean
    24      * @param beanName
    25      * @return
    26      * @throws BeansException
    27      * @author diandian.zhang
    28      * @date 2017年10月25日下午7:07:02
    29      * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
    30      */
    31     @Override
    32     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    33         System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!beanName="+beanName);
    34         return bean;
    35     }
    36     
    37     /**
    38      * 
    39      * @Description 初始化后,处理器
    40      * @param bean
    41      * @param beanName
    42      * @return
    43      * @throws BeansException
    44      * @author diandian.zhang
    45      * @date 2017年10月25日下午7:07:07
    46      * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
    47      */
    48     @Override
    49     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    50         System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!beanName="+beanName);
    51         return bean;//注意,如果返回null,后续BeanPostProcessor不会再执行
    52     }
    53 
    54     
    55 }

    4.自定义实例化bean后处理器适配器,复写postProcessBeforeInstantiation、postProcessBeforeInstantiation、postProcessPropertyValues分别对应实例化Bean前调用、实例化Bean后调用、设置某个属性时调用

    注意:InstantiationAwareBeanPostProcessorAdapter ,这里是实例化Instantiation,不是初始化Initialization!!!

     1 package spring.ioc;
     2 
     3 import java.beans.PropertyDescriptor;
     4 
     5 import org.springframework.beans.BeansException;
     6 import org.springframework.beans.PropertyValues;
     7 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
     8 
     9 /**
    10  * 
    11  * @ClassName:MyInstantiationAwareBeanPostProcessor
    12  * @Description:BeanPostProcessor的子类,增加了更多自定方法
    13  * @author diandian.zhang
    14  * @date 2017年10月25日下午7:09:15
    15  */
    16 public class MyInstantiationAwareBeanPostProcessor extends
    17         InstantiationAwareBeanPostProcessorAdapter {
    18 
    19     public MyInstantiationAwareBeanPostProcessor() {
    20         super();
    21         System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
    22     }
    23 
    24     // 接口方法、实例化Bean之前调用
    25     @Override
    26     public Object postProcessBeforeInstantiation(Class<?> beanClass,String beanName) throws BeansException {
    27         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法[实例化Bean之前调用 ]beanname="+beanName);
    28         return null;
    29     }
    30 
    31     // 接口方法、实例化Bean之后调用
    32     @Override
    33     public Object postProcessAfterInitialization(Object bean, String beanName)
    34             throws BeansException {
    35         System.out .println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法[实例化Bean之后调用]beanname="+beanName);
    36         return bean;
    37     }
    38 
    39     // 接口方法、设置某个属性时调用
    40     @Override
    41     public PropertyValues postProcessPropertyValues(PropertyValues pvs,
    42             PropertyDescriptor[] pds, Object bean, String beanName)
    43             throws BeansException {
    44         System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法 pvs="+pvs+",beanName="+beanName);
    45         return pvs;
    46     }
    47 }

    5.测试类,使用ClassPathXmlApplicationContext从xml中读取bean配置文件生成applicationContext容器应用上下文,这一步对应容器初始化。第二部从应用上下文中获取bean。最后一步注册一个关闭钩子,在容器关闭时触发。

     1 package spring.ioc;
     2 
     3 import org.junit.Test; 6 import org.springframework.context.ApplicationContext;
     7 import org.springframework.context.support.ClassPathXmlApplicationContext;10 
    11 import spring.aop.xml.dao.Dao;
    12 
    13 /**
    14  * 
    15  * @ClassName:IOCTest
    16  * @Description:测试类
    17  * @author diandian.zhang
    18  * @date 2017年10月25日下午4:42:01
    19  */
    22 public class IOCTest {
    35     
    36     @Test
    37     public void iocPersonTest(){
    38         System.out.println("=============容器初始化======start=========");
    39         @SuppressWarnings("resource")
    40         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("simple_spring_bean.xml");//源码入口
    41         System.out.println("=============容器初始化=======end========");
    42         System.out.println("=============获取person bean====start=======");
    43         Person person = applicationContext.getBean("person",Person.class);//获取Bean
    44         System.out.println("=============获取person bean====end=======,person类名="+person.getClass().getName());
    45         System.out.println("=============注册关闭钩子,关闭容器(JVM shutdown)时触发钩子!================");
    46         ((ClassPathXmlApplicationContext)applicationContext).registerShutdownHook();
    47     }
    48 }

    直接运行,结果如下:

    =============容器初始化======start=========
    log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
    log4j:WARN Please initialize the log4j system properly.
    [MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor实现类构造器!!
    [MyBeanFactoryPostProcessor工厂后处理器]BeanFactoryPostProcessor.postProcessBeanFactory()获取bean定义后添加属性mobile=110
    这是BeanPostProcessor实现类构造器!!
    这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
    InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法[实例化Bean之前调用 ]beanname=person
    [构造器] 调用Person的构造器实例化
    InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法 pvs=PropertyValues: length=2; bean property 'mobile'; bean property 'name',beanName=person
    [属性注入] mobile=110
    [属性注入] name=张三
    [接口BeanNameAware.setBeanName() ]
    [接口BeanFactoryAware.setBeanFactory() ]
    BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!beanName=person
    [接口InitializingBean.afterPropertiesSet() ]
    [init-method]调用<bean>的init-method属性指定的初始化方法
    BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!beanName=person
    InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法[实例化Bean之后调用]beanname=person
    =============容器初始化=======end========
    =============获取person bean====start=======
    =============获取person bean====end=======,person类名=spring.ioc.Person
    =============注册关闭钩子,关闭容器(JVM shutdown)时触发钩子!================
    [接口DisposableBean.destroy() ]
    [destroy-method]调用<bean>的destroy-method属性指定的销毁方法

    总结流程:

    ====================================

    参考

    1.JDK8源码

    2.全文参考Spring Bean的生命周期(非常详细),

  • 相关阅读:
    hdu-1698(线段树,区间修改)
    hdu-1394(线段树)
    hdu-1166(线段树)
    hdu-1251(string+map)
    hdu-1711(kmp算法)
    hdu-2191(完全背包+二进制优化模板)
    hdu-2844(完全背包+二进制优化模板)
    hdu-1171(多重背包+二进制优化)
    SpringMVC 参数中接收数组、List写法
    如何高效的查询数组中是否包含某个值
  • 原文地址:https://www.cnblogs.com/dennyzhangdd/p/7732273.html
Copyright © 2011-2022 走看看