### 准备

## 目标

了解 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. java 新手入门课程03

    2017.7.6  java 课堂笔记 1.关于分支; if/else 是基于boolean 值的双分支 Switch  基于数字(包括整数 char byte  枚举, 字符串)类型的多分支  方法 ...

  2. angular自定义指令命名的那个坑

    Directive 先从定义一个简单的指令开始. 定义一个指令本质上是在HTML中通过元素.属性.类或注释来添加功能.AngularJS的内置指令都是以ng开头,如果想自定义指令,建议自定义一个前缀代 ...

  3. django自带权限机制

    1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发,理清Django权限机制是 ...

  4. 入坑-DM导论-第一章绪论笔记

    //本学习笔记只是记录,并未有深入思考. 1.什么是数据挖掘? 数据挖掘是数据库中发现必不可少的一部分. 数据预处理主要包括(可能是最耗时的步骤): 1.融合来自多个数据源的数据 2.清洗数据以消除噪 ...

  5. cocos代码研究(16)Widget子类RadioButton学习笔记

    理论基础 RadioButton是一种特定类型的两状态按钮,它与复选框相似.它可以 和RadioButtonGroup一起使用,形成一个"组".继承自AbstractCheckBu ...

  6. Excel error 64-bit version of SSIS

    问题是 在windows server 2008 64位的计划任务执行 ssis 的错误 ,ssis你们带有读取excel 日期 2015/3/17 11:50:34日志 作业历史记录 (SSIS_U ...

  7. poj1981 Circle and Points

    地址:http://poj.org/problem?id=1981 题目: Circle and Points Time Limit: 5000MS   Memory Limit: 30000K To ...

  8. 《零起点,python大数据与量化交易》

    <零起点,python大数据与量化交易>,这应该是国内第一部,关于python量化交易的书籍. 有出版社约稿,写本量化交易与大数据的书籍,因为好几年没写书了,再加上近期"前海智库 ...

  9. open-falcon设置报警邮件

    下载编译好的二进制包并解压: https://files.cnblogs.com/files/dylan-wu/mail-provider.tar.gz [root@localhost work]# ...

  10. Python 无穷大与NaN

    想创建或测试正无穷.负无穷或NaN(非数字) 的浮点数 Python 并没有特殊的语法来表示这些特殊的浮点值,但是可以使用float() 来创建它们.比如: >>> a = floa ...