zoukankan      html  css  js  c++  java
  • 【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,下午。

  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10813269.html
Copyright © 2011-2022 走看看