### 准备

## 目标

了解 Spring 如何初始化 bean 实例

##测试代码

gordon.study.spring.ioc.IOC04_Initialization.java
public class IOC04_Initialization {
 
    public static void main(String[] args) {
        Resource resource = new ClassPathResource("ioc/ioc04.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        BeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);
        reader.loadBeanDefinitions(resource);
        factory.addBeanPostProcessor(new InnerBeanPostProcessor());
        InnerClass inner = factory.getBean("inner", InnerClass.class);
        System.out.println("level: " + inner.level);
        factory.destroySingleton("inner");
    }
 
    static class InnerBeanPostProcessor implements BeanPostProcessor {
 
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("in postProcessBeforeInitialization()...");
            return bean;
        }
 
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("in postProcessAfterInitialization()...");
            if (bean instanceof InnerClass) {
                ((InnerClass) bean).level = 3;
            }
            return bean;
        }
    }
 
    static class InnerClass implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
 
        private int level;
 
        public InnerClass() {
            System.out.println("construct InnerClass...");
        }
 
        @Override
        public void setBeanName(String name) {
            System.out.println("in setBeanName()..." + name);
        }
 
        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {
            System.out.println("in setBeanClassLoader()..." + classLoader);
        }
 
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("in setBeanFactory()..." + beanFactory);
        }
 
        public void setLevel(int level) {
            System.out.println("in setLevel()...");
            this.level = level;
        }
 
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("in afterPropertiesSet()...");
            level = 2;
        }
 
        @Override
        public void destroy() throws Exception {
            System.out.println("in destroy()...");
        }
 
        public void init() {
            System.out.println("in init()...");
        }
 
        public void exit() {
            System.out.println("in exit()...");
        }
    }
}
 
ioc04.xml
<beans ...>
    <bean id="inner" class="gordon.study.spring.ioc.IOC04_Initialization$InnerClass" init-method="init" destroy-method="exit">
        <property name="level" value="1" />
    </bean>
</beans>
 
执行结果
construct InnerClass...
in setLevel()...
in setBeanName()...inner
in setBeanClassLoader()...sun.misc.Launcher$AppClassLoader@73d16e93
in setBeanFactory()...org.springframework.beans.factory.support.DefaultListableBeanFactory@2d8f65a4: defining beans [inner]; root of factory hierarchy
in postProcessBeforeInitialization()...
in afterPropertiesSet()...
in init()...
in postProcessAfterInitialization()...
level: 3
in destroy()...
in exit()...
 

### 分析

## 文档描述

BeanFactory 类的文档描述了 bean 生命周期中对外提供的扩展点。
 
Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:
  1. BeanNameAware's setBeanName
  2. BeanClassLoaderAware's setBeanClassLoader
  3. BeanFactoryAware's setBeanFactory
  4. EnvironmentAware's setEnvironment
  5. EmbeddedValueResolverAware's setEmbeddedValueResolver
  6. ResourceLoaderAware's setResourceLoader (only applicable when running in an application context)
  7. ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context)
  8. MessageSourceAware's setMessageSource (only applicable when running in an application context)
  9. ApplicationContextAware's setApplicationContext (only applicable when running in an application context)
  10. ServletContextAware's setServletContext (only applicable when running in a web application context)
  11. postProcessBeforeInitialization methods of BeanPostProcessors
  12. InitializingBean's afterPropertiesSet
  13. a custom init-method definition
  14. postProcessAfterInitialization methods of BeanPostProcessors
 
On shutdown of a bean factory, the following lifecycle methods apply:
  1. postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors
  2. DisposableBean's destroy
  3. a custom destroy-method definition
 

## 示例代码分析

InnerClass 首先通过默认构造函数被实例化,输出 construct InnerClass...
 
接着装配属性,调用 setLevel 方法设置 level 属性,输出 in setLevel()...
 
然后就开始初始化 bean。通过 AbstractAutowireCapableBeanFactory 的 initializeBean 方法。
 
 
按照文档描述,Spring 框架先按顺序处理 BeanNameAware(1), BeanClassLoaderAware(2) 和 BeanFactoryAware(3),对应代码第1615行。
 
接着,第1620行代码处理 BeanPostProcessors 的 beforeInitialization 扩展点(11)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor 的 postProcessBeforeInitialization 方法。
 
然后,第1624行代码调用初始化方法:如果 bean 是 InitializingBean 实例,则调用 afterPropertiesSet 方法(12);如果 XML 文件中还定义了 init-method,则通过反射调用 init-method(13)。此外,Spring 框架尽力保证同一个初始化方法不会执行多次(可以尝试将 init-method 修改为 "afterPropertiesSet",看看执行结果)。
 
最后,第1633行代码处理BeanPostProcessors 的 afterInitialization 扩展点(14)。遍历 List<BeanPostProcessor> beanPostProcessors,调用每个 BeanPostProcessor的 postProcessAfterInitialization方法。
 
 

Spring IOC 源码简单分析 04 - bean的初始化的更多相关文章

  1. Spring IOC 源码简单分析 02 - Bean Reference

    ### 准备 ## 目标 了解 bean reference 装配的流程 ##测试代码 gordon.study.spring.ioc.IOC02_BeanReference.java   ioc02 ...

  2. Spring IOC 源码简单分析 03 - 循环引用

    ### 准备 ## 目标 了解 Spring 如何处理循环引用 ##测试代码 gordon.study.spring.ioc.IOC03_CircularReference.java   ioc03. ...

  3. Spring IOC 源码简单分析 01 - BeanFactory

    ### 准备 ## 目标 了解 Spring IOC 的基础流程 ## 相关资源 Offical Doc:http://docs.spring.io/spring/docs/4.3.9.RELEASE ...

  4. Spring Ioc源码分析系列--Bean实例化过程(一)

    Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...

  5. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

  6. Spring Ioc源码分析系列--容器实例化Bean的四种方法

    Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...

  7. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  8. spring IoC源码分析 (3)Resource解析

    引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource  ...

  9. Spring Ioc源码分析系列--Ioc的基础知识准备

    Spring Ioc源码分析系列--Ioc的基础知识准备 本系列文章代码基于Spring Framework 5.2.x Ioc的概念 在Spring里,Ioc的定义为The IoC Containe ...

随机推荐

  1. 微信小程序 --- 下拉刷新上拉加载

    查看文档看到:page()函数注册页面的时候,有 onPullDownRefresh 监听用户下拉动作,onReachBottom 页面上拉触底事件的函数. 在小程序里,用户顶部下拉是默认禁止的,我们 ...

  2. Hadoop命令别名

    [hadoop@master ~]$ alias hdfs='hadoop dfs' [hadoop@master ~]$ hdfs -ls / drwxrwxr-x   - hadoop super ...

  3. ROM和RAM的故事

    在公众号里看到一篇很好的文章讲解rom和ram,之前也是一直不能理解两者的区别,今天就转载记下来吧.也方便大家学习. 因为我刚开始学习的时候总喜欢刨根问底,一个问题要是不搞清楚,后面学习都会很吃力的. ...

  4. jquery操作select标签change事件

    $('#update_supply_id').on('change',function(){//判断是否选取prompt属性,无返回值: if($(this).val()){ var selectTe ...

  5. 基于JDK1.8的String源码学习笔记

    String,可能是学习Java一上来就学习的,经常用,但是却往往只是一知半解,甚至API有时也得现查.所以还是老规矩,倒腾源码. 一.java doc 这次首先关注String的doc,因为其实作为 ...

  6. apidemos编译出错

    编译api 19的(4.4.2)apidemos一直报xml相关资源出错. 把build-toos 22删除,替换成19版本的,就ok了. 真是坑啊. 学习新东西难免遇到坑.

  7. This module embeds Lua, via LuaJIT 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model.

    openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers https://github.com/openre ...

  8. Linux入门之常用命令(15) lsof

    查看磁盘空间: [root@ticketb ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 981M 203M 729M ...

  9. centos Linux系统日常管理1 cpuinfo cpu核数 命令 w, vmstat, uptime ,top ,kill ,ps ,free,netstat ,sar, ulimit ,lsof ,pidof 第十四节课

    centos Linux系统日常管理1  cpuinfo cpu核数   命令 w, vmstat, uptime ,top ,kill ,ps ,free,netstat ,sar, ulimit ...

  10. LCS 最长公共子序列

    区别最长公共子串(连续) ''' LCS 最长公共子序列 ''' def LCS_len(x, y): m = len(x) n = len(y) dp = [[0] * (n + 1) for i ...