• 【spring源码分析】IOC容器初始化——查漏补缺(四)


    前言:在前几篇查漏补缺中,其实我们已经涉及到bean生命周期了,本篇内容进行详细分析。


    首先看bean实例化过程:

    分析:

    bean实例化开始后

    • 注入对象属性后(前面IOC初始化十几篇文章)。
    • 检查激活Aware接口。
    • 执行BeanPostProcessor前置处理
    • 实例化bean,这里会检查InitializingBean和init-method方法。
    • 执行BeanPostProcessor后置处理
    • 注册销毁bean的回调方法(并不是必须)。
    • 使用bean。
    • 检查DisposableBean和destroy-method方法。

    注意:Spring是不会主动去调用销毁方法,必须我们主动告知Spring容器。

    示例

     1 public class BeanLifeCycle implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
     2 
     3     private String msg;
     4 
     5     public BeanLifeCycle() {
     6         System.out.println("调用构造函数:BeanLifeCycle()");
     7     }
     8 
     9     public String getMsg() {
    10         return msg;
    11     }
    12 
    13     public void setMsg(String msg) {
    14         System.out.println("属性注入:setMsg");
    15         this.msg = msg;
    16     }
    17 
    18     @Override
    19     public void setBeanName(String name) {
    20         System.out.println("BeanNameAware#setBeanName 被调用");
    21     }
    22 
    23     @Override
    24     public void setBeanClassLoader(ClassLoader classLoader) {
    25         System.out.println("BeanClassLoaderAware#setBeanClassLoader 被调用");
    26     }
    27 
    28     @Override
    29     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    30         System.out.println("BeanFactoryAware#setBeanFactory 被调用");
    31 
    32     }
    33 
    34     @Override
    35     public void afterPropertiesSet() throws Exception {
    36         System.out.println("InitializingBean#afterPropertiesSet 被调用,并对msg属性进行修改");
    37         this.msg = "InitializingBean#afterPropertiesSet方法对msg属性进行修改";
    38     }
    39 
    40     @Override
    41     public void destroy() throws Exception {
    42         System.out.println("DisposableBean#destroy 被调用");
    43     }
    44 
    45     public void initMethod() {
    46         System.out.println("init-method 被调用,并对msg属性进行修改,调用顺序在InitializingBean之后");
    47         this.msg = "init-method方法对msg属性进行修改";
    48     }
    49 
    50     public void destroyMethod() {
    51         System.out.println("destroy-method 被调用,调用顺序在DisposableBean之后");
    52     }
    53 }

    上述为主测试类,另外为了测试BeanPostProcessor,我们还需增加如下测试类:

     1 public class BeanLifeCycleBeanPostProcessor implements BeanPostProcessor {
     2 
     3     @Override
     4     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     5         System.out.println("beanName=" + beanName + " 初始化之前调用:BeanPostProcessor#postProcessBeforeInitialization!!!!!");
     6         return bean;
     7     }
     8 
     9     @Override
    10     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    11         System.out.println("beanName=" + beanName + " 初始化之后调用:BeanPostProcessor#postProcessAfterInitialization!!!!!");
    12         return bean;
    13     }
    14 }

    具体配置如下:

    1 <bean id="beanLifeCycle" class="com.dev.basebean.lifecycle.BeanLifeCycle"
    2           init-method="initMethod" destroy-method="destroyMethod" p:msg="属性注入"/>
    3     <bean id="beanLifeCycleBeanPostProcessor" class="com.dev.basebean.lifecycle.BeanLifeCycleBeanPostProcessor"/>

    测试代码:

    1     @Test
    2     public void beanLifeCycleTest() {
    3         ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/lifecycle/lifecycle.xml");
    4         BeanLifeCycle beanLifeCycle = context.getBean(BeanLifeCycle.class);
    5         System.out.println("msg=" + beanLifeCycle.getMsg());
    6         ((ClassPathXmlApplicationContext) context).close();
    7     }

    运行结果如下:

    通过以上运行结果,我们可知Bean的生命周期,总结如下:

    1. Spring容器根据实例化策略对Bean进行实例化(调用其构造方法)。
    2. 实例化完成后,如果该bean设置了一些属性,则利用set方法进行属性设置。
    3. 如果该bean实现了BeanNameAware接口,则调用其setBeanName方法。
    4. 如果该bean实现了BeanClassLoaderAware接口,则调用其setBeanClassLoader方法。
    5. 如果该bean实现了BeanFactoryAware接口,则调用其setBeanFactory方法。
    6. 如果容器中注册了BeanPostProcessor,则会调用其postProcessBeforeInitialization方法,完成bean前置处理。
    7. 如果该bean实现了InitializingBean接口,则调用其afterPropertiesSet方法。
    8. 如果该bean配置了init-method方法,则调用其指定的方法。
    9. 初始化完成后,如果容器中注册了BeanPostProcessor,则会调用其postProcessAfterInitialization方法,完成bean后置处理。
    10. 对象初始化完成,就可以使用bean了(对其进行各种骚操作,上述示例中调用了getMsg方法)。
    11. 在容器关闭之前,如果该bean实现了DisposableBean接口,则调用其destroy方法。
    12. 在容器关闭之前,如果该bean配置了destroy-method方法,则调用其指定方法。

    至此bean的生命周期结束,该bean完成了其伟大的一生。


    by Shawn Chen,2019.05.05,下午。

  • 相关阅读:
    审 讯 技巧
    带参数的多线程的方式
    通达信日线 数据格式
    visual studio 2012 update3
    单实例运行tz
    维特比算法
    Kooboo CMS的安装步骤
    年龄
    富文本编辑器---非常实用的
    printf 打印 unit32_t
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10813269.html
Copyright © 2020-2023  润新知