Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)
去年通过实际框架代码的阅读,以及结合《Spring源码深度解析》和《Spring技术内幕》的阅读,对Spring框架内Bean模块有了一个整体性的认识。对此进行的总结性整理和回顾。
一、Spring IOC容器简述
如果将对象相关合作对象的引用或依赖关系的管理直接有具体对象来完成,这样会导致代码的高度耦合性和可测试下的降低。也就是说如果相关合作的引用的对象直接在某一个具体的对象之中进行硬代码不利于合作对象
之间的耦合。 如果将合作对象的引用或者依赖关系交由第三方组件(也就是Spirng IOC容器)来管理对象合作对象的引用和依赖关系的管理(通过依赖注入实现)。这样维护对象间依赖关系的控制权就转移至框架当中,降
低了对象之间的耦合度(也就是控制反转)。
Spring IOC提供了一个基本的JavaBean容器(可以说是beanDefinitionMap ),通过IOC模式管理依赖关系,并通过依赖注入和AOP切面增强了为JavaBean这样的POJO对象赋予事务管理,生命周期管理等基本功能。
DefaultListableBeanFactory.java
/** Map of bean definition objects, keyed by bean name */
//已经完成注册加载的Bean即容器持有载入的BeanDefinition private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
二、Spring IOC容器的结构
Spring框架针对不同的使用场景提供多个不同的功能各异的容器供用户选择和使用。BeanFacotry是IOC容器的最基本形式,其派生出了不同使用场景下的更加高级的IOC容器。
Spring IOC容器是什么实现的?
BeanFactory接口定义了获取Bean及Bean 的各种属性,提供了最基本的IOC容器的功能,是所有容器的基类。Spring框架根据不同的开发场景分别提供了不同的容器包括ApplicationContext、XmlBeanFactory、
ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext等。
(1)容器的层次结构
1) BeanFactory –>HierarchicalBeanFactory –> ConfigurableBeanFactory
HierarchicalBeanFactory接口继承了BeanFactory之后,增加了getParentBeanFactory()的接口功能,是BeanFactory具备了双亲IOC容器的管理功能
ConfigurableBeanFactory接口主要定义了一些对BeanFactory的配置功能
2)BeanFactory –>AutowireCapableBeanFactory
AutowireCapableBeanFactory 接口扩展BeanFactory接口增强了自动装配的功能
3)BeanFactory -> ListabaleBeanFactory
ListabaleBeanFactory接口扩展BeanFactory接口,提供所有bean 实例的枚举,不再需要客户端通过一个个bean name查找
4)BeanFactory –>HierarchicalBeanFactory –> ConfigurableBeanFactory
–>AutowireCapableBeanFactory
–>ListabaleBeanFactory
–>ConfigurableListableBeanFactory –>DefaultListableBeanFactory ->AbstractAutowireCapableBeanFactory ->AbstractBeanFactory
ConfigurableListableBeanFactory接口:继承了ConfigurableBeanFactory 接口,AutowireCapableBeanFactory接口,ListabaleBeanFactory接口 ,提供了对bean定义的分析和修改的便利方法,同时也提供了对单例的预实例化
DefaultListableBeanFactory接口:
AbstractAutowireCapableBeanFactory接口:
AbstractBeanFactory接口:
5)BeanFactory –>HierarchicalBeanFactory
–>AutowireCapableBeanFactory
–>ListabaleBeanFactory
–>ApplicationContext –>WebApplicationContext
ApplicationContext接口:
WebApplicationContext接口:
6)FileSystemXmlApplicationContext
FileSystemXmlApplicationContext接口:是一个支持XML定义的BeanDefinition的ApplicationContext,并且可以指定以文件形式的BeanDefinition的读入,这些文件可以使用网络路径和URL定义来表示。
7)ClassPathXmlApplicationContext
ClassPathXmlApplicationContext接口:一个从Class路径读取BeanDefinition定义文件的ApplicationContext
(2)容器内部的结构和表示
1)Bean的表示(Bean在容器内的抽象,即Bean标签的表示)
Spring内Bean是如何表示的?
BeanDefinition是对我们所定义的Bean的抽象,Spring框架通过它来管理基于Spring 的应用中的各种对象以及它们之间的相互依赖关系。简单的说BeanDefinition就是对象依赖关系的抽象。
BeanDefinitionHolder接口:持有一个BeanDefinition,并持有该BeanDefinition的所有别名(alias)
AliasDefinition接口:对应于alias标签的
ImportDefintion接口:对应于import标签
在Spring中BeanDefinition存在三种实现:RootBeanDefition、ChildBeanDefition、GenericBeanDefition 三者均继承于AbstractBeanDefition
RootBeanDefition类表示嵌套bean内的父<bean>,而ChildBeanDefition表示子<bean>
2)Bean配置文件的读取(Resource到Document)
3)Bean标签的解析(创建AbstractBeanDefinition)
4)Bean标签的注册
Spring将配置文件内的<bean>转化为容器的内部表示BeanDefiniton后将其注册到BeanDefinitionRegistry
BeanDefinitionRegistry接口:就像是Spring配置信息的内存数据库,主要以map的形式保存,后续操作直接从BeanDefinitionRegistry读取配置信息
5)Bean的初始化和加载
三、容器的实现过程(初始化过程)
BeanFactory bf=new XmlBeanFactory(new ClassPathResource(“test.xml”)); MyBean myBean=(MyBean)bf.getBean(“myBean”);
1、Resource 资源文件的抽象

2、加载配置文件(从Resource到Document)
从指定的配置资源路径(“test.xml”)加载配置文件,并将获取到的文件输入流转换为XML文档格式(即创建Document对象),也就是从根据指定路径的ClassPathResource对象(Resource)加载配置文件并将配
置文件转换为Document对象.

3、解析填充BeanDefinition
把配置文件转换为Document后,就需要从Document中提取各个定义的标签进行解析并将其注册到Spring IOC容器内(即添加到beanDefinitionMap 内)。 需要解析的标签有: bean标签、 alias标签、 import标
签、 beans标签、自定义标签,标签的解析过程也是创建BeanDefinition设置属性值的过程.
(1)bean标签的解析
(2)import标签的解析
(3)alias标签的解析
(4)beans标签的解析
(5)自定义标签的解析:

4、加载Bean
Bean在Spring同一个容器内只会被创建一次,后续再获取bean则直接从单例缓存中尝试获取,如果没有获取到则再次从单例工厂中(singletonFactories)加载。
(1)尝试从缓存中获取
(2)获取单例Bean

5、创建Bean
(待续)
6、容器的功能扩展
(待续)
Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)的更多相关文章
- CI框架源码阅读笔记5 基准测试 BenchMark.php
上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- CI框架源码阅读笔记2 一切的入口 index.php
上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里再次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中, ...
- CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程
最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时 ...
- Spring事务源码阅读笔记
1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...
- CI框架源码阅读笔记8 控制器Controller.php
最近时间有些紧,源码阅读系列更新有些慢.鉴于Controller中代码比较少,本次Blog先更新该文件的源码分析. 在经过路由分发之后,实际的应用Controller接管用户的所有请求,并负责与用户数 ...
- 干货分享之Spring框架源码解析01-(xml配置解析)
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea Spring 是一个工厂,是一个负责对象的创建和维护的工厂.它给我 ...
- Spring框架源码干货分享之三级缓存和父子工厂
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 建议:学习过程中要开着源码一步一步过 Spring中对象的创建宏观 ...
随机推荐
- Down Payment 和 Deposit的差异
If you’re like most homeowners, purchasing a home represents the single biggest financial transactio ...
- Mysql 中如何创建触发器
use websitelogdb; #创建表 CREATE TABLE `test` ( `idtest` int(11) NOT NULL AUTO_INCREMENT, `testcol` var ...
- MySQL利用xtrabackup在线修复或新增从库
如果数据库的数据量很大,表大小有几十个G,利用mysqldump导出备份会消耗非常长的时间,会对数据库产生不稳定风险,这时可以利用xtrabackup工具在线复制主库文件,利用复制出来的主库文件可以修 ...
- 【Spark深入学习 -15】Spark Streaming前奏-Kafka初体验
----本节内容------- 1.Kafka基础概念 1.1 出世背景 1.2 基本原理 1.2.1.前置知识 1.2.2.架构和原理 1.2.3.基本概念 1.2.4.kafka特点 2.Kafk ...
- C++数值类型与string的相互转换
转自:https://www.cnblogs.com/johngu/p/7878029.html 1.数值类型转换为string 1.1使用函数模板+ostringstream 使用函数模板将基本数据 ...
- sed用法去除行首和行末的中括号
sed去掉行首和行末的中括号: sed -i 's:^\[::; s:\]$::;' newtrace_nlp.log.2018-08-02.bak 其余可依次类推.
- 解决ubuntu下IntelliJ IDEA无法锁定到启动器的问题
参考:https://www.zhihu.com/question/31626161 在目录~/.local/share/applications 中找到以前的IDEA的.desktop文件,删掉即可
- 【nodejs】初识 NodeJS(一)
构建一个基础的 http 服务器 需要引用 http 模块,http 模块是 node.js 的内置模块. var http = require('http'); http.createServer( ...
- 万能分布式消费框架,添加基于redis中间件的方式。
框架目的是分布式调度起一切任何函数(当然也包括调度起一切任何方法). 之前写的是基于rabbitmq的,作为专用的消息队列好处比redis的list结构好很多.但有的人还是强烈喜欢用redis,以及r ...
- dos 打开计算机管理
一. 首先打开[运行]程序:二. 运行中输入‘CMD’:三. 然后在上面输入‘compmgmt.msc’,就可以打开“计算机管理”命令了.





