spring源码:核心组件(li)
Posted 为爱奔跑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)的主要内容,如果未能解决你的问题,请参考以下文章