Spring框架的设计理念

Spring的骨骼架构

Spring的核心组件只有三个:Core、Context和Bean,而AOP、Web这样的上层特性功能都是在这三个的基础上构建的

设计理念

三个核心组件中的核心是Bean组件,Spring可以给视为面向Bean编程

Bean对于Spring的作用就是Object对OOP的意义一样,Spring解决的一个非常关的问题就是,可以让你把对象之间的依赖关系转而用配置文件来管理,也就是依赖注入机制,而Ioc容器中存在的,就是被Bean包裹的对象

核心组件如何协调工作

Bean包装的是Object,而Object必然有数据,如何给这些数据提供生存环境就是Context要解决的问题,对于Context来说就是要发现每个Bean之间的关系,然后为它们建立这种关系并进行维护,所以Context就是一个Bean关系的集合

而Core就是发现、建立和维护每个Bean之间的关系所需要的一系列工具,Core更像是一个Util

核心组件详解

Bean组件

Bean组件在Spring的org.springframework.beans包下,这个包下所有的类主要解决了三个问题:Bean的定义、Bean的创建以及对Bean的解析,对于使用者来说只需关系Bean的创建

Bean的创建时典型的工厂模式,顶级接口时BeanFactory,其有三个子类:ListableBeanFactory、HierarchiaclBeanFactory和AutowireCapableBeanFactory,但其实最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。定义这么多层次的接口是为了适配各种使用的场景,区分在Spring内部对象的传递和转化的过程中对对象数据访问所做的限制。例如ListableBeanFactory接口表示这些Bean是可列表的,HierarchiaclBeanFactory表示这些类是有继承关系的,也就是每个Bean可能有父Bean,AutowireCapableBeanFactory接口定义Bean的自动装配规则

Bean的定义主要由BeanDefinition描述,完整地描述了在Spring的配置文件中你定义的节点中所有的信息,包括各种子节点。当Spring成功解析定义的第一个节点后,在Spring的内部它就被转化成BeanDefinition对象,后续所有的操作都是对这个对象来进行的

而Bean的解析过程很复杂,功能划分很细,被拓展的地方很多,保证有足够的灵活性。Bean的解析主要就是对Spring的配置文件的解析

Context组件

Context在org.springframework.context包下,实际上就是给Spring提供一个运行时的环境,以保存各个对象的状态

ApplicationContex是context的顶级父类,除了能标识一个应用环境的而基本信息外,还继承了5个接口,拓展context的功能

ApplicationContex继承了BeanFactory,这点说明了Spring容器中运行的主体对象是Bean。另外,ApplicationContext继承了ResourceLoader接口,使得其可以访问到任何外部资源

ApplicationContex的子类主要包含两个方面:

  1. configurableApplicationContext表示该Context是可以修改的,也就是在构建Context中,用户可以动态添加或者修改已有的配置信息
  2. WebApplication是为Web准备的Context,可以直接访问ServletContext

总的来说,ApplicaitonContext必须要完成以下几件事情:

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

context作为Spring的Ioc容器,基本上整合了Spring的大部分功能

Core组件

其一个重要的组成部分就是定义了资源的访问方式,将所有的资源抽象成一个接口

Resource接口封装了各种可能的资源类型,也就是对使用者来说屏蔽了文件类型的不同

Resource接口继承了InputSreamSource接口,在接口中有个getInputSream方法,返回InputStream类,这样屏蔽了资源的提供者

资源的加载任务是由ResourceLoader接口完成的,它屏蔽了所有的资源加载者的差异,只要实现这个接口就可以加载所有的资源,默认实现为DefultResourceLoader

Ioc容器的工作

创建BeanFatory工厂

Ioc容器实际上是Context组件结合其他两个组件共同构建了一个Bean关系网,如果就在AbstractApplicationContext类的refresh方法中,主要包含以下几个步骤:

  1. 构建BeanFactory
  2. 注册可能感兴趣的事件
  3. 创建Bean实例对象
  4. 触发被监听的事件

创建Bean实例并构建Bean的关系网

  1. 从finishBeanFactoryInitialization方法开始
  2. Bean的实例化实在BeanFactory中发生的
  3. 一个非常重要的Bean:FactoryBean,Spring中一大半的拓展功能都与这个Bean有关,这是一个特殊的Bean。其是一个工厂Bean,可以产生Bean实例的Bean,通过继承FactoryBean并实现它的getObject方法即可自定义产生实例对象的方法

Ioc容器的扩展点

  1. BeanFactoryPostProcessor:构建BeanFactory时被调用
  2. BeanPostProcessor:构建Bean对象时被调用
  3. InitializingBean:创建Bean实例时被调用
  4. DisPosableBean:销毁Bwan实例时被调用

以上四点就是常见通过实现在这些接口中定义方法来拓展Ioc使得Spring完成我们自定义的任务

AOP

动态代理的实现原理

JDK的java.lang.reflect包下面有一个Proxy类,这个就是构造代理类的入口,这个类有个方法为newProxyInstance,这个就是创建代理对象的地方。此方法需要三个参数:

  1. ClassLoader:用于加载代理类的Loader类,通常和被代理的类时同一个类
  2. Interfaces:要被代理的接口
  3. InvocationHandler:用于执行除了被代理接口中方法之外的用户自定义的操作,也是用户需要代理的最终目的。用户调用目标方法都被代理到在InvocationHandler类中定义的唯一方法invoke()中

Spring AOP如何实现

代理的目的时调用目标方法时可以转而执行InvocationHandler类的invoke方法,因此Spring实现AOP的关键就是在Invocation上做文章

Spring引用了Aop Allicance定义的接口。要实现代理类,在Spring的配置文件定义Bean的时候要设置被代理的接口和接口的实现类(目标类),以及拦截器

从代理类上来看,其继承了FactoryBean的ProxyFactory,也就是之前提到的Spring自身的拓展点

在Spring创建了代理对象后,当调用目标对象上的方法时,都会被代理到InvocationHandler类的invoke方法中执行