### 准备

## 目标

了解 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. web站点检查简易shell脚本

    1.web样式 <h4>THE STATUS OF RS:</h4> <meta http-equiv="> <table border=" ...

  2. 二维坐标系极角排序的应用(POJ1696)

    Space Ant Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3170   Accepted: 2029 Descrip ...

  3. mysql数据库新插入数据,需要立即获取最新插入的id

    在MySQL中,使用auto_increment类型的id字段作为表的主键.通常的做法,是通过“select max(id) from tablename”的做法,但是显然这种做法需要考虑并发的情况, ...

  4. java 常见几种发送http请求案例

    import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java ...

  5. Windows上的巧克力味Chocolatey详解

    Chocolatey是什么?很简单,Chocolatey就是Windows系统的yum或apt-get. 一.Chocolatey介绍 Chocolatey是一款专为Windows系统开发的.基于Nu ...

  6. WebDriver API 实例详解(二)

    十一.双击某个元素 被测试网页的html源码: <html> <head> <meta charset="UTF-8"> </head&g ...

  7. loadrunner11的移动端性能测试之脚本优化

    测试步骤之脚本优化(Script) 看到这里,是不是疑惑录制好的脚本还需要优化吗,答案是肯定的. 优化概要 脚本优化包括插入注释(Comment),插入事务(Transaction),插入检查点(Ch ...

  8. PAT 1128 N Queens Puzzle[对角线判断]

    1128 N Queens Puzzle(20 分) The "eight queens puzzle" is the problem of placing eight chess ...

  9. 创建工具条ToolBar

    /***ToolBar***/ QToolBar * tlb_ImageOpen; QToolBar * tlb_VideoOpen; QToolBar * tlb_AudioOpen; void M ...

  10. 制造抽象基类--《C++必知必会》 条款33

    抽象类,含有纯虚函数的类,不可以创建对象. 然而,有时我们并不需要某个函数定义为纯虚函数,但是任然希望此类像抽象类一样,不可以创建对象. 方法1:通过确保类中不存在共有构造函数来模拟抽象基类的性质.意 ...