spring源码:核心组件(li)
一、AOP实现
Spring代理对象的产生:代理的目的是调用目标方法时我们可以转而执行InvocationHandler类的invoke方法,所以如何在InvocationHandler上做文章就是Spring实现Aop的关键所在。Spring的代理类正是继承了Factory Bean的ProxyFactoryBean,ProxyFactoryBean之所以特别就在它可以让你自定义对象的创建方法。当然代理对象要通过Proxy类来动态生成。下面是Spring创建的代理对象的时序图:Spring创建了代理对象后,当你调用目标对象上的方法时,将都会被代理到InvocationHandler类的invoke方法中执行。在这里JdkDynamicAopProxy类实现了InvocationHandler接口。
Spring是调用拦截器,Spring调用拦截器的时序图如下:
二、IOC容器的初始化过程
Spring提供了一个BeanFactory的基本实现,XmlBeanFactory同样的通过使用模板模式来得到对IOC容器的抽象-AbstractBeanFactory,DefaultListableBeanFactory这些抽象类为其提供模板服务。其中通过resource 接口来抽象bean定义数据,对Xml定义文件的解析通过委托给XmlBeanDefinitionReader来完成。简单的演示IOC容器的创建过程:
ClassPathResource res = new ClassPathResource("beans.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(res);
这些代码演示了以下几个步骤:
- 创建IOC配置文件的抽象资源
- 创建一个BeanFactory
- 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory
- 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程。我们的IoC容器就建立起来了。
实际上,Spring的IoC容器初始化包括:Bean定义资源文件的定位、载入和注册3个基本过程。
- Bean定义资源文件的定位: Bean定义资源文件定位由ResourceLoader通过统一的Resource接口来完成,Resource接口将各种形式的Bean定义资源文件封装成统一的、IoC容器可进行载入操作的对象。 通过ResourceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以从类路径,文件系统, URL等方式来定为资源位置。如果是XmlBeanFactory作为IOC容器,那么需要为它指定bean定义的资源,也就是说bean定义文件时通过抽象成Resource来被IOC容器处理的。
- Bean定义资源文件的载入: Bean定义资源文件载入的过程是将Bean定义资源文件中配置的Bean转换成IoC容器中所管理Bean的数据结构形式。Spring IoC中管理 的Bean的数据结构是BeanDefinition,BeanDefinition是POJO对象在IoC容器中的抽象。容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册,往往使用的是XmlBeanDefinitionReader来解析bean的xml定义文件,实际的处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示 。这个名字可以让我们想到loadBeanDefinition,RegisterBeanDefinition这些相关的方法,他们都是为处理BeanDefinitin服务的。
- Bean定义的注册:IoC容器解析得到BeanDefinition以后,需要把它在IOC容器中注册,这由IOC实现 BeanDefinitionRegistry接口来实现。注册过程就是在IOC容器内部维护的一个HashMap来保存得到的 BeanDefinition的过程。这个HashMap是IoC容器持有bean信息的场所,以后对bean的操作都是围绕这个HashMap来实现的。
三、Spring IOC容器的设计
两条主线:第一条主线:从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路线。
- BeanFactory接口定义了基本的IoC容器的规范。基本定义了获取bean和获取判断bean全局范围类型等。
- HierarchicalBeanFactory,提供了getParentBeanFactory,使BeanFactory具备了双亲IoCring容器管理能力,和containsLocalBean(String name)两个方法。
- ConfigurableBeanFactory,主要定义了一些对BeanFactory的配置功能。
第二条主线:第二条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到ConfigurableApplicationContext或WebApplicationContext。
- ListableBeanfactory接口继承了 BeanFactory 的同时,提供了列举 Bean 的功能,他能够列举当前 BeanFactory 加载的所有 Bean :列举所有 Bean 的名字或者满足某种类型的 Bean 的名字,根据类型返回所有 Bean 对象 , 等。但是它无法获取上层 BeanFactory 加载的单例 Bean 。
- HierarchicalBeanFactory 比较简单,它主要是提供父 BeanFactory 的功能,通过它能够获取当前 BeanFactory 的父工厂( PS: 若在 A 工厂启动并加载 Bean 之前, B 工厂先启动并加载了,那 B 就是 A 的父工厂),这样就能让当前的 BeanFactory 加载父工厂加载的 Bean 了,弥补了 ListableBeanfactory 欠缺的功能。
- ConfigurableBeanFactory 就是在 HierarchicalBeanFactory 的基础上增加了可配置的功能,包括注册别名、注册单例等,设置 Classloader 、是否缓存 Bean Metadata 、设置 TypeConverter 、 BeanPostProcessor 、配置 Bean 依赖等。 PS:ConfigurableBeanFactory 还继承了 SingletonBeanRegistry 定义了一个注册singleton bean的容器,用来定义为用来共享的 bean 实例的注册表。此接口可以被BeanFactory的实现实现,用来形成一个统一管理singleton bean的风格。
- AutowireCapableBeanFactory ,主要是提供自动 Bean 自动绑定 ( 或者说自动装配 ) 功能。例如根据自动装配策略 new 一个 bean ,为已有的 bean 装配属性依赖;还有创建 bean 之后的回调功能,为 bean 设置 name 、 bean factory 、 bean post processor 等;将 bean post processor 应用到 bean 的初始化,等等。
- MessageSource用来支持国际化。
- ResourceLoader接口用于实现不同的Resource加载策略,即将不同Resource实例的创建交给ResourceLoader来计算。在ResourceLoader接口中,主要定义了一个方法:getResource(),它通过提供的资源location参数获取Resource实例。
- ApplicationEventPublisher接口作为事件发布者,并且ApplicationContext实现了这个接口,担当起了事件发布者这一角色。
四、Spring总体架构
Spring总共有十几个组件,但是真正核心的组件只有三个:Core、Context和Beans。它们构建起了整个Spring的骨骼架构。没有它们就不可能有AOP、Web等上层的特性功能。
- Spring就是面向Bean的编程(BOP,Bean Oriented Programming),Bean在Spring 中才是真正的主角。Bean在Spring中作用就像Object对OOP的意义一样,没有对象的概念就像没有面向对象编程,Spring中没有Bean也就没有Spring存在的意义。Spring解决了一个非常关键的问题是把对象之间的依赖关系转而用配置文件来管理,也就是依赖注入机制。而这个注入关系在一个叫Ioc容器中管理,那Ioc容器中存放的就是被Bean包裹的对象。Spring正是通过把对象包装在 Bean中而达到对这些对象管理以及一些列额外操作的目的。
- Context就是一个Bean关系的集合,这个关系集合又叫Ioc容器。如果把Bean比作一场演出中的演员的话,那Context就是这场演出的舞台背景。
- Core就是发现、建立和维护每 个Bean之间的关系所需要的一些列的工具,从这个角度看来,Core这个组件叫Util更能理解一些。
五、核心组件
Bean组件在Spring的org.springframework.beans包下。这个包下的所有类主要解决了三件事:Bean的定义、Bean 的创建以及对Bean的解析。
如上图所示:Bean的创建时典型的工厂模式,他的顶级接口是BeanFactory,下图是这个工厂的继承层次关系。
如上图所示:Bean的定义主要有BeanDefinition描述,如下图说明了这些类的层次关系。Bean的定义就是完整的描述了在Spring的配置文件中你定义的节点中所有的信息,包括各种子节点。当Spring成功解析完定义的一个节点后,在Spring的内部就被转化成BeanDefinition对象。
如上图所示:Bean的解析过程非常复杂,功能被分的很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean的解析主要就是对Spring配置文件的解析。这个解析过程主要通过下图中的类完成。
Context组件:Context在Spring的org.springframework.context包下。ApplicationContext是Context的顶级父类,他除了能标识一个应用环境的基本信息外,他还继承了五个接口,这五个接口主要是扩展了Context的功能。下面是Context的类结构图,从上图中可以看出ApplicationContext继承了BeanFactory,这也说明了Spring容器中运行的主体对象是Bean。
ApplicationContext的子类主要包含两个方面:
- ConfigurableApplicationContext表示该Context是可修改的,也就是在构建Context中用户可以动态添加或修改已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的Context,即 AbstractRefreshableApplicationContext类。
- WebApplicationContext顾名思义,就是为web准备的Context他可以直接访问到ServletContext,通常情况下,这个接口使用的少。
再往下分就是按照构建Context的文件类型,接着就是访问Context的方式。这样一级一级构成了完整的Context等级层次。总体来说ApplicationContext必须要完成以下几件事:
- 标识一个应用环境
- 利用BeanFactory创建Bean对象
- 保存对象关系表
- 能够捕获各种事件
Context作为Spring的Ioc容器,基本上整合了Spring的大部分功能,或者说是大部分功能的基础。
Core组件,Core组件作为Spring的核心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了资源的访问方式。下图是Resource相关的类结构图。
Resource接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,Resource 接口继承了InputStreamSource接口,这个接口中有个getInputStream方法,返回的是InputStream类。这样所有的资源都被可以通过InputStream这个类来获取,所以也屏蔽了资源的提供者。ResourceLoader接口屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源, 他的默认实现是DefaultResourceLoader。
Context和Resource的关系:Context是把资源的加载、解析和描述工作委托给了ResourcePatternResolver类来完成,他相当于一个接头人,他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。
六、
spring源码:核心组件(li)的更多相关文章
- spring源码:学习线索(li)
一.spring xml配置(不包括AOP,主要了解在初始化及实例化过程中spring配置文件中每项内容的具体实现过程,从根本上掌握spring) <bean>的名字 &,alia ...
- spring源码:web容器启动(li)
web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- spring源码分析(一)IoC、DI
创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕 ...
- spring源码分析系列 (5) spring BeanFactoryPostProcessor拓展类PropertyPlaceholderConfigurer、PropertySourcesPlaceholderConfigurer解析
更多文章点击--spring源码分析系列 主要分析内容: 1.拓展类简述: 拓展类使用demo和自定义替换符号 2.继承图UML解析和源码分析 (源码基于spring 5.1.3.RELEASE分析) ...
- 转 Spring源码剖析——核心IOC容器原理
Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...
- spring 源码解析
1. [文件] spring源码.txt ~ 15B 下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB 下载( ...
- Spring源码系列 — Envoriment组件
何为Envoriment Envoriment是集成在Spring上下文容器中的核心组件,在Spring源码中由Envoriment接口抽象. 在Environment中,有两大主要概念: Profi ...
- 【Spring源码分析】预备篇
前言 最新想学习一下Spring源码,开篇博客记录下学习过程,欢迎一块交流学习. 作为预备篇,主要演示搭建一个最简单的Spring项目样例,对Spring进行最基本梳理. 构建一个最简单的spring ...
- Spring学习之——手写Spring源码V2.0(实现IOC、D、MVC、AOP)
前言 在上一篇<Spring学习之——手写Spring源码(V1.0)>中,我实现了一个Mini版本的Spring框架,在这几天,博主又看了不少关于Spring源码解析的视频,受益匪浅,也 ...
随机推荐
- 初学seaJs模块化开发,利用grunt打包,减少http请求
原文地址:初学seaJs模块化开发,利用grunt打包,减少http请求 未压缩合并的演示地址:demo2 学习seaJs的模块化开发,适合对seajs基础有所了解的同学看,目录结构 js — —di ...
- Android Weekly Notes Issue #237
Android Weekly Issue #237 December 25th, 2016 Android Weekly Issue #237 这是本年的最后一篇issue, 感谢大家. 本期内容包括 ...
- Impress.js上手 - 抛开PPT、制作Web 3D幻灯片放映
前言: 如果你已经厌倦了使用PPT设置路径.设置时间.设置动画方式来制作动画特效.那么Impress.js将是你一个非常好的选择. 用它制作的PPT将更加直观.效果也是嗷嗷美观的. 当然,如果用它来装 ...
- ABP文档 - Web Api 控制器
文档目录 本节内容: 简介 AbpApiController 基类 本地化 其它 过滤 审计日志 授权 防伪造过滤 工作单元 结果包装和异常处理 结果缓存 验证 模块绑定器 简介 通过Abp.Web. ...
- .NET 基础 一步步 一幕幕[数组、集合、异常捕获]
数组.集合.异常捕获 数组: 一次性存储多个相同类型的变量. 一维数组: 语法: 数组类型[] 数组名=new 数组类型[数组长度]; 声明数组的语法: A.数据类型 [] 数组名称= new 数据类 ...
- PHP中多线程处理
php多进程处理 往往我们会碰到一个情况,需要写一个脚本,这个脚本要处理的数据量极大,单进程处理脚本非常慢,那么这个时候就会想到使用多进程或者多线程的方式了. 我习惯使用多进程的方式,php中使用多进 ...
- Windows 10 安装SVN 不显示状态图标--解决方法
升级win10以后,什么都正常,就是svn版本库图标不见了,图标的显示有助于我们定位代码的修改及提交情况,该怎么办呢? 下面分享详细的解决办法亲测有用: 其实也比较简单, 在注册表中找到此项: HKE ...
- hadoop2.7.1 HA安装部署(转)
hadoop集群规划 目标:创建2个NameNode,做高可用,一个NameNode挂掉,另一个能够启动:一个运行Yarn,3台DataNode,3台Zookeeper集群,做高可用. 在 hadoo ...
- Math.abs()方法 取绝对值
定义和用法 abs() 方法可返回数的绝对值. 语法 Math.abs(x) 参数 描述 x 必需.必须是一个数值. 返回值 x 的绝对值. 实例 在本例中,我将取得正数和负数的绝对值: <sc ...
- cmder添加右键菜单
http://www.jianshu.com/p/b691b48bcee3 就这么简单 Cmder.exe /REGISTER ALL