### 准备

## 目标

了解 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. 微信小程序 --- app.js文件

    app.js文件是项目的入口文件: //app.js App({ onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('l ...

  2. oneThink添加成功,返回到当前请求地址!

    其实没什么,就一行代码: $this->success('已采纳',$_SERVER['HTTP_REFERER']);

  3. C++程序风格的思考

    转载自:http://www.cppblog.com/weiym/archive/2013/04/27/199781.html 发现厚积薄发中有很多值得学习的东西 故引用之: 最近有机会看号称是公司最 ...

  4. collision weaknesses

    15.1. hashlib — Secure hashes and message digests — Python 3.5.6 documentation https://docs.python.o ...

  5. describe neural networks as a series of computational steps via a directed graph.

    https://www.microsoft.com/en-us/research/product/cognitive-toolkit/ https://github.com/microsoft/cnt ...

  6. SmartSprites 智能批量合并 CSS 雪碧图

    做前端的稍微有点经验的都知道 可以通过合并小图片 来减少请求数, 最早可能都是通过 fw.ps 等工具来手动合并, 这种方式的缺点就不吐槽了,效率低,可维护性差 等等 .... 一些很厉害的人,往往会 ...

  7. Nginx文件下载服务器

    1. 配置文件 server { listen 80; #端口 server_name localhost; #服务名 charset utf-8; #避免中文乱码 root /data/packag ...

  8. 13.Github使用

    我们一直用GitHub作为免费的远程仓库,如果是个人的开源项目,放到GitHub上是完全没有问题的.其实GitHub还是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人 ...

  9. EasyUI Progressbar 进度条

    通过 $.fn.progressbar.defaults 重写默认的 defaults. 进度条(progressbar)提供了一种显示长时间操作进度的反馈.进度可被更新以便让用户知道当前正在执行的操 ...

  10. Windows7系统运行hadoop报Failed to locate the winutils binary in the hadoop binary path错误

    程序运行的过程中,报Failed to locate the winutils binary in the hadoop binary path  Java.io.IOException: Could ...