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);  

这些代码演示了以下几个步骤:

  1. 创建IOC配置文件的抽象资源
  2. 创建一个BeanFactory
  3. 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory
  4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程。我们的IoC容器就建立起来了。

实际上,Spring的IoC容器初始化包括:Bean定义资源文件的定位、载入和注册3个基本过程。 

  1. Bean定义资源文件的定位: Bean定义资源文件定位由ResourceLoader通过统一的Resource接口来完成,Resource接口将各种形式的Bean定义资源文件封装成统一的、IoC容器可进行载入操作的对象。 通过ResourceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以从类路径,文件系统, URL等方式来定为资源位置。如果是XmlBeanFactory作为IOC容器,那么需要为它指定bean定义的资源,也就是说bean定义文件时通过抽象成Resource来被IOC容器处理的。
  2. 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服务的。
  3. Bean定义的注册:IoC容器解析得到BeanDefinition以后,需要把它在IOC容器中注册,这由IOC实现 BeanDefinitionRegistry接口来实现。注册过程就是在IOC容器内部维护的一个HashMap来保存得到的 BeanDefinition的过程。这个HashMap是IoC容器持有bean信息的场所,以后对bean的操作都是围绕这个HashMap来实现的。

三、Spring IOC容器的设计

两条主线:第一条主线:从接口BeanFactory到HierarchicalBeanFactory,再到ConfigurableBeanFactory,是一条主要的BeanFactory设计路线。

  1. BeanFactory接口定义了基本的IoC容器的规范。基本定义了获取bean和获取判断bean全局范围类型等。
  2. HierarchicalBeanFactory,提供了getParentBeanFactory,使BeanFactory具备了双亲IoCring容器管理能力,和containsLocalBean(String name)两个方法。
  3. ConfigurableBeanFactory,主要定义了一些对BeanFactory的配置功能。

  第二条主线:第二条接口设计主线是,以ApplicationContext应用上下文接口为核心的接口设计,这里涉及的主要接口设计有,从BeanFactory到ListableBeanFactory,再到ApplicationContext,再到ConfigurableApplicationContext或WebApplicationContext。

  1. ListableBeanfactory接口继承了 BeanFactory 的同时,提供了列举 Bean 的功能,他能够列举当前 BeanFactory 加载的所有 Bean :列举所有 Bean 的名字或者满足某种类型的 Bean 的名字,根据类型返回所有 Bean 对象 , 等。但是它无法获取上层 BeanFactory 加载的单例 Bean 。
  2. HierarchicalBeanFactory 比较简单,它主要是提供父 BeanFactory 的功能,通过它能够获取当前 BeanFactory 的父工厂( PS: 若在 A 工厂启动并加载 Bean 之前, B 工厂先启动并加载了,那 B 就是 A 的父工厂),这样就能让当前的 BeanFactory 加载父工厂加载的 Bean 了,弥补了 ListableBeanfactory 欠缺的功能。
  3. ConfigurableBeanFactory 就是在 HierarchicalBeanFactory 的基础上增加了可配置的功能,包括注册别名、注册单例等,设置 Classloader 、是否缓存 Bean Metadata 、设置 TypeConverter 、 BeanPostProcessor 、配置 Bean 依赖等。 PS:ConfigurableBeanFactory 还继承了 SingletonBeanRegistry 定义了一个注册singleton bean的容器,用来定义为用来共享的 bean 实例的注册表。此接口可以被BeanFactory的实现实现,用来形成一个统一管理singleton bean的风格。
  4. AutowireCapableBeanFactory ,主要是提供自动 Bean 自动绑定 ( 或者说自动装配 ) 功能。例如根据自动装配策略 new 一个 bean ,为已有的 bean 装配属性依赖;还有创建 bean 之后的回调功能,为 bean 设置 name 、 bean factory 、 bean post processor 等;将 bean post processor 应用到 bean 的初始化,等等。
  5. MessageSource用来支持国际化。
  6. ResourceLoader接口用于实现不同的Resource加载策略,即将不同Resource实例的创建交给ResourceLoader来计算。在ResourceLoader接口中,主要定义了一个方法:getResource(),它通过提供的资源location参数获取Resource实例。
  7. ApplicationEventPublisher接口作为事件发布者,并且ApplicationContext实现了这个接口,担当起了事件发布者这一角色。

四、Spring总体架构

  Spring总共有十几个组件,但是真正核心的组件只有三个:Core、Context和Beans。它们构建起了整个Spring的骨骼架构。没有它们就不可能有AOP、Web等上层的特性功能。

  1. Spring就是面向Bean的编程(BOP,Bean Oriented Programming),Bean在Spring 中才是真正的主角。Bean在Spring中作用就像Object对OOP的意义一样,没有对象的概念就像没有面向对象编程,Spring中没有Bean也就没有Spring存在的意义。Spring解决了一个非常关键的问题是把对象之间的依赖关系转而用配置文件来管理,也就是依赖注入机制。而这个注入关系在一个叫Ioc容器中管理,那Ioc容器中存放的就是被Bean包裹的对象。Spring正是通过把对象包装在 Bean中而达到对这些对象管理以及一些列额外操作的目的。
  2. Context就是一个Bean关系的集合,这个关系集合又叫Ioc容器。如果把Bean比作一场演出中的演员的话,那Context就是这场演出的舞台背景。
  3. 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的子类主要包含两个方面:

  1. ConfigurableApplicationContext表示该Context是可修改的,也就是在构建Context中用户可以动态添加或修改已有的配置信息,它下面又有多个子类,其中最经常使用的是可更新的Context,即 AbstractRefreshableApplicationContext类。
  2. WebApplicationContext顾名思义,就是为web准备的Context他可以直接访问到ServletContext,通常情况下,这个接口使用的少。

再往下分就是按照构建Context的文件类型,接着就是访问Context的方式。这样一级一级构成了完整的Context等级层次。总体来说ApplicationContext必须要完成以下几件事:

  1. 标识一个应用环境
  2. 利用BeanFactory创建Bean对象
  3. 保存对象关系表
  4. 能够捕获各种事件

Context作为Spring的Ioc容器,基本上整合了Spring的大部分功能,或者说是大部分功能的基础。

  Core组件,Core组件作为Spring的核心组件,他其中包含了很多的关键类,其中一个重要组成部分就是定义了资源的访问方式。下图是Resource相关的类结构图。 

  Resource接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说,如何把资源包装起来交给其他人用这也是一个问题,Resource 接口继承了InputStreamSource接口,这个接口中有个getInputStream方法,返回的是InputStream类。这样所有的资源都被可以通过InputStream这个类来获取,所以也屏蔽了资源的提供者。ResourceLoader接口屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源, 他的默认实现是DefaultResourceLoader。

  Context和Resource的关系:Context是把资源的加载、解析和描述工作委托给了ResourcePatternResolver类来完成,他相当于一个接头人,他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。

六、

时间: 2024-10-14 03:16:20

spring源码:核心组件(li)的相关文章

spring源码:学习线索(li)

一.spring xml配置(不包括AOP,主要了解在初始化及实例化过程中spring配置文件中每项内容的具体实现过程,从根本上掌握spring) <bean>的名字 &,alias,id(名称的转换,绑定) 属性及构造函数参数注入 (注入过程,类型转换) 依赖解析 (显示依赖和自动依赖解析 depends-on,autowire,dependency-check) 继承(extends) 作用域(singleton,prototype,session等,不同作用域的bean的具体实例

spring源码:web容器启动(li)

web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomcat,jboss等,以jetty为例,我们看一下web容器是如何初始化和启动spring的context. 一.Spring容器的加载 在web工程中都有一个web.xml文件,jetty在启动的时候会加载这个配置文件,并且对文件中的各个listener进行加载.ContextLoaderListe

spring源码分析(一)IoC、DI

创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕> 参考文章:http://www.cnblogs.com/xing901022/p/4178963.html http://www.myexception.cn/program/1031276.html http://blog.csdn.net/qian_348840260/article/detai

Spring源码阅读:Spring AOP设计与实现(一):动态代理

在Spring的有两个核心:IOC与AOP,AOP又是基于动态代理模式实现的.所以要了解SpringAOP是如何设计的之前,还是先了解一下Java中的动态代理比较好. 认识代理模式 代理模式是这么描述的: 代理模式是为其他对象提供一种代理以控制对这个对象的访问 代理对象的功能: 通过创建一个代理对象,用这个代理对象去代理真实的对象,客户端得到这个代理对象后,对客户端并没有什么影响,就跟真实的对象一样(因为代理对象和真是对象实现了同一接口). 下面看看代理模式的类图: 解说: RealSubjec

SPRING源码解析-SPRING 核心-IOC

IoC 和 AOP是Spring的核心, 是Spring系统中其他组件模块和应用开发的基础.透过这两个模块的设计和实现可以了解Spring倡导的对企业应用开发所应秉承的思路: 易用性. POJO开发企业应用, 直接依赖于Java语言,而不是容器和框架. 提升程序的可测试性,提高软件质量. 提供一致性编程模型,面向接口的编程 降低应用的负载和框架的侵入性.IoC和AOP实现. 不作为现有解决方案的替代,而是集成现有. IoC和AOP这两个核心组件,特别是IoC容器,使用户在使用Spring完成PO

Spring源码学习之一下载和导入

折腾了两天spring源码,一直都不能成功导入eclipse,今天早上上班前试了最后一次,总算BUILD SUCCESSFUL了,特此纪念一下. 一.下载spring源码,https://github.com/spring-projects/spring-framework/tree/v4.2.3.RELEASE.在linux mint系统里用git下载了一遍了,window系统的git用起来实在掣肘,所以直接下载zip压缩包了,解压. 二.更新jdk1.8_66,spring4需要用到jdk8

Spring源码下载

Spring已经将源码从SVN迁移到了Github,而且也改为基于Gradle的构建来构建项目,它取代了之前的ANT+Ivy系统,所以要构建Spring源码要先安装Github和Gradle. 首先假设各位已经将成功的安装了Github和Gradle了. Gradle下载之后要进行环境变量的配置:类似JDK的配置,这里配置GRADLE_HOME和path. 下面就是下载源码,并编译成eclipse可以识别的工程的步骤. 1.首先打开Github,输入命令cd e://Spring,即定位源码下载

spring 源码导入eclipse(sts)

一. 准备工作 1.下载安装sts(springsource推荐使用) 下载地址: http://www.springsource.org/downloads/sts-ggts 2.下载安装gradle, spring 源码构建加入了万恶的gradle 下载地址带详细说明: https://gradle.org/install/ 3. 安装配置完成验证 注意本人使用的 JDK 版本和 万恶的 Gradle 版本,必须是 1.6(亲测,4.0 build failure) 4.下载安装spring

将Spring源码转换为工程 + 导入Eclipse时缺失jar包

将源码转换为工程: 比如查看Spring事务部分的源码. 打开cmd窗口,切换到Spring-tx文件夹下,执行命令 "gradle cleanidea eclipse" . 缺失jar包: 第一步:切换到spring源码的lib目录 第二步:解压lib目录下的spring-core-4.2.6.RELEASE.jar文件 第三步:在cmd窗口下切换到第二步中解压的spring-core-4.2.6.RELEASE目录 第四步:使用jar命令生成需要的jar文件 (jar cvf sp

Spring源码 之环境搭建

1.安装gitHub 在官网https://desktop.github.com/下载githubsetup.exe,在线安装总是出错,试了几次后不成功就放弃了.不知道是不是网络的原因. 后来在网上找了个离线安装的安装包 地址如下:http://download.csdn.net/detail/nevinblog/9031049 2.安装Gradle Gradle是一个基于Groovy的构建工具,它使用Groovy来编写构建脚本,支持依赖管理和多项目创建,类似Maven,但比其更加简单轻便. 在