### 准备

## 目标

了解 Spring IOC 的基础流程

## 相关资源

Sample code:<https://github.com/gordonklg/study>,spring module
源码版本:Spring framework 4.3.9

##测试代码

gordon.study.spring.ioc.IOC01_DefaultListableBeanFactory.java

 
ioc01.xml
<beans ...>
     <bean id="message" class="gordon.study.spring.common.Message">
        <property name="body" value="Hello World!" />
    </bean>
</beans>

### 分析

## 整体流程分析

org.springframework.core.io.Resource 是 Spring 抽象出来的代表底层资源的接口,从这些资源可以获得输入流(InputStream)。代码第16行创建了一个 org.springframework.core.io.ClassPathResource 实例,表示是相对于类路径的文件资源。
 
org.springframework.beans.factory.support.DefaultListableBeanFactory 是本次分析的核心。DefaultListableBeanFactory 实现了 org.springframework.beans.factory.BeanFactory 接口,BeanFactory 接口定义了访问 Spring bean 容器的方法,通过该接口,我们可以从容器中获取预先配置的 bean。BeanFactory 接口定义了以下方法:
 
BeanFactory 接口中最重要的方法就是 getBean(String),通过 bean name 获得指定的实例。代码第20行就是通过 getBean 方法从 bean 容器中获得 Message 类的实例。
 
为了能够从 BeanFactory 中获取 bean 实例,BeanFactory 的实现类首先应该能获得 bean 定义,例如本例中通过 xml 文件配置的 message bean,这就需要为 bean 定义设计一个数据模型,在 Spring 中,org.springframework.beans.factory.config.BeanDefinition 接口用来表示 bean 定义。
 
所有的 bean 定义应该放到同一个地方以便管理,org.springframework.beans.factory.support.BeanDefinitionRegistry 相当于 BeanDefinition 的注册表,为 Spring IOC 提供对 BeanDefinition 的注册、获取操作。
 

Spring IOC 框架设计时决定让 BeanFactory 的实现类同时承担 BeanDefinitionRegistry 的职能,所以 DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口,同时包含一个 Map<String, BeanDefinition> beanDefinitionMap 属性作为 BeanDefinition 的注册表。
 
有了存放 BeanDefinition 的注册表,我们还需要工具类从配置文件中读取出 bean 定义,第18行的 org.springframework.beans.factory.xml.XmlBeanDefinitionReader 用来从 xml 格式的配置文件中读取出 bean 定义,并将 bean 定义注册到其构造函数指定的 BeanDefinitionRegistry 实例中(本例中为  DefaultListableBeanFactory 实例)。第19行调用 loadBeanDefinitions 方法从指定 Resource 中读取 bean 定义。
 

## BeanFactory.getBean 流程分析

当程序执行到第20行准备从 bean 容器中获取实例时,可以发现 DefaultListableBeanFactory 中已经成功读取到 BeanDefinition 信息:
List<String> beanDefinitionNames - [message]
Map<String, BeanDefinition> beanDefinitionMap - {message=Generic bean: class [gordon.study.spring.common.Message]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [ioc/ioc01.xml]}
 
第20行 getBean 在本例中的核心流程如下:
  1. 尝试从 singletonObjects 中获取名字为 message 的 bean 实例
    由于 bean 默认是 Singleton 类型,所以 DefaultListableBeanFactory 中包含属性 Map<String, Object> singletonObjects 用来缓存所有 Singleton 类型实例。只有当指定名字的 Singleton 实例尚未被创建时才会创建实例,否则直接返回已创建的实例。
  2. 将 bean 标记为已创建(或即将创建完成)状态。就是将 bean name 放到 Set<String> alreadyCreated 中。
  3. 根据 BeanDefinition 生成 RootBeanDefinition,RootBeanDefinition 可以看做是合并过的最终 bean 定义。在本例中,RootBeanDefinition 与 BeanDefinition 基本一致,除了将原来值为空的 scope 改为 singleton。- Root bean: class [gordon.study.spring.common.Message]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [ioc/ioc01.xml]
  4. 将 RootBeanDefinition 放到 Map<String, RootBeanDefinition> mergedBeanDefinitions 中。
  5. 流经一个很复杂的过程,根据 RootBeanDefinition 中的信息,通过反射创建出 bean 实例,并装配好属性,再将 bean 实例放入 Map<String, Object> singletonObjects 中。
 
 
 
 
 

Spring IOC 源码简单分析 01 - BeanFactory的更多相关文章

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

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

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

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

  3. Spring IOC 源码简单分析 04 - bean的初始化

      ### 准备 ## 目标 了解 Spring 如何初始化 bean 实例 ##测试代码 gordon.study.spring.ioc.IOC04_Initialization.java publ ...

  4. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  5. Spring IOC 源码分析

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

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

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

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

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

  8. Spring Ioc源码分析系列--前言

    Spring Ioc源码分析系列--前言 为什么要写这个系列文章 首先这是我个人很久之前的一个计划,拖了很久没有实施,现在算是填坑了.其次,作为一个Java开发者,Spring是绕不开的课题.在Spr ...

  9. Spring Ioc源码分析系列--Ioc源码入口分析

    Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...

随机推荐

  1. 微信小程序 --- 获取设备信息

    获取设备信息: wx.getSystemInfo model:手机型号 pixelRatio:设备像素比 windowWidth:窗口宽度 windowHeight:窗口高度 language:语言 ...

  2. 310实验室OTL问题(2)

    1.PyOptimization代码学习心得 (1).该部分由三个分块组成(按完成的相应的任务).第一部分,运行函数. 以optimization.py为入口程序,其思路是:首先获取路径,然后,初始化 ...

  3. 【git】------git开发过程中的使用流程------【巷子】

    001.创建仓库 002.新建项目 003.初始化仓库  这一步不需要做 git init : 文件夹中会多出一个隐藏的.git文件 004.克隆项目 git clone <项目地址> 0 ...

  4. JQueryUI之Autocomplete

    JQueryUI之Autocomplete JQuery UI 是以 JQuery 为基础的开源 JavaScript 网页用户界面代码库.包含底层用户交互.动画.特效和可更换主题的可视控件,这些控件 ...

  5. WebService 的简单使用

    简单介绍 WebService是一种跨语言,跨进程,跨机器的数据交互技术. SOAP:简单对象访问协议,通过XML数据交互的轻量级协议,WebService就是采用的这种协议 WSDL:web服务描述 ...

  6. java 中关于System.out.println()的问题

    Java 的输出知识 1.System.out.println()不能直接写在类中,例如: 因为在 Class A{ //成员变量 //构造方法 //普通方法 //内部类 } 如果硬是想使用Syste ...

  7. SQL和access随机数

    Access: CLng(Rnd(种子数字)*1000000)   SQL Server ceiling(rand(abs(checksum(newid())))*1000000)    

  8. 洛谷P5151 HKE与他的小朋友 快速幂/图论+倍增

    正解:矩阵快速幂/tarjan+倍增 解题报告: 传送门! 跟着神仙做神仙题系列III 这题首先一看到就会想到快速幂趴?就会jio得,哦也不是很难哦 然而,看下数据范围,,,1×105,,,显然开不下 ...

  9. 【抓包】火狐浏览器F12

    页面请求服务器的get.post两种请求,还有其他种,但是其他中基本不用,所以只记住get和post两种请求方法即可. 1.get(当前页面向服务器传值--即请求服务器)---弊端--传值长度有限 F ...

  10. C++中的RAII介绍 资源管理

    摘要 RAII技术被认为是C++中管理资源的最佳方法,进一步引申,使用RAII技术也可以实现安全.简洁的状态管理,编写出优雅的异常安全的代码. 资源管理 RAII是C++的发明者Bjarne Stro ...