Spring框架的设计理念

Spring是面向Bean的编程(Bean Oriented Programming, BOP),Bean在Spring中的作用就像Object对OOP的意义一样,没有对象的概念就没有面向对象编程,在Spring中没有Bean也就没有Spring存在的意义。Spring解决了一个非常关键的问题,它可以让你把对象之间的关系转为用配置文将来管理(也有用JavaConfig或注解),也就是它的依赖注入机制。而这个注入关系在一个叫Ioc的容器中管理,Spring正是通过把对象包装在Bean中从而达到管理这些对象以及做一系列额外操作的目的

核心组件

Spring的核心组件包括Bean,Context和Core。Bean主要只为了包裹Object,使得对象成为一种特殊的对象(Bean)存在Spring中,而Context就是为了发现每个Bean之间的关系,为它们建立这种关系并且维护好这种关系。所以Context就是一个Bean关系的合集,这个关系集合又叫Ioc容器,一旦建立起这个Ioc容器,Spring就可以为你工作了。Core就是发现,建立和维护每个Bean之间的关系所需要的一系列工具,更像是Util工具集合

Bean组件

Bean组件在Spring的org.springframework.beans包下,在这个包下所有的类主要解决了3件事:Bean的定义,Bean的创建以及对Bean的解析。对Spring的使用者来说唯一需要关心的就是Bean的创建,其他两个由Spring在内部完成,为你来说透明

Spring Bean的创建是典型的工厂模式,它的顶级接口是BeanFactory。BeanFactory有3个子类:ListableBeanFactory,HierarchicalBeanFactory和AutowireCapableBeanFactory。在BeanFactory的继承关系中最终的默认实现类是DefaultListableBeanFactory,它实现了所有的接口。Spring设计这么多接口,只要是为了区分在Spring内部传递和转发过程中,对对象的数据访问所做的限制。例如ListableBeanFactory接口表示这些Bean是可以列表的,而HierarchicalBeanFactory表示这些Bean是有继承关系的,也就是每个Bean有可能有父Bean,AutowriteCapableBeanFactory接口定义Bean的自动装配规则,这三个接口共同定义了Bean的集合,Bean之间的关系和Bean的行为

Bean的定义完整地描述了在Spring配置文将中你所定义的<bean/>节点中所有的信息,包括各种子节点。当Spring成功解析你定义的一个<bean/>节点后,在Spring的内部它就被转化为BeanDefinition对象,以后所有的操作都是对这个对象进行的

Bean的解析只要就是对Spring配置文件或者配置类进行解析

Context组件

Context在Spring的org.springframework.context包下,它实际上就是给Spring提供一个运行时的环境,用于保存每个对象的状态,ApplicationContext是Context的顶级父类,它除了能够标识一个应用环境的基本信息外,还扩展了Context的功能,同时ApplicationContext还继承了BeanFactory,这也说明了Spring容器中运行的主体对象是Bean

总体来说,ApplicationContext必须完成以下几件事情

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

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

Core组件

Core组件作为Spring的核心组件,其中包含了很多关键类,一个重要的组成部分就是定义了资源的访问方式。Resource接口就是封装了这种资源类型,对使用者来说屏蔽了文件类型的不同,Resource接口继承了InputStreamSource接口,在这个接口中有个getInputStream方法,返回的是InputStream类。这样所有资源都可以通过InputStream类来获取,所以也屏蔽了资源得提供者,还有一个问题就是加载资源的问题,资源的加载也应该统一,这个任务是由ResourceLoader接口完成的,它屏蔽了所有资源加载者的差异,只需要实现这个接口就可以加载资源了,它的默认实现类是DefaultResourceLoader

IOC容器如何工作

如何创建BeanFactory工厂

Ioc容器实际上是Context组件组合其他两个组件共同构建了一个Bean关系网,构建这个关系网的入口就在AbstractApplicationContext类的refresh方法,这个方法

1.首先创建和配置BeanFactory,当BeanFactory已存在就更新,如果不存在就新创建。BeanFactory的原始对象是DefauleListableBeanFactory

2.创建好BeanFactory后,添加一些Spring本身需要的工具类,这个操作在AbstractApplicationContext的prepareBeanFactory方法中完成

3.接下来可以对已经构建的BeanFactory的配置做修改,或者对以后再创建的Bean实例对象时添加一些自定义操作,这些操作是通过后置处理器(PostProcessors)去完成的

4.最后就是初始化监听事件和对系统的其他监听者的注册,监听者必须是ApplicationListener的子类

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

Bean的实例化是在BeanFactory类的finishBeanFactoryInitialization方法开始的

这个过程中会涉及到一个重要的Bean——FactoryBean,这是一个特殊的Bean,采用工厂模式的Bean,可以产生Bean实例的Bean。如果一个类继承FactoryBean,用户可以自定义产生Bean实例对象的方法,只需要去实现它的getObject方法即可

普通的Bean通过调用getBean方法直接创建实例

IOC容器的扩展点

对Spring的Ioc容器来说,,主要有后置处理器BeanFactoryPostProcessorBeanPostProcessor,它们分别在构建BeanFactory和构建Bean对象时调用。还有就是InitializingBeanDisposableBean,它们分别在Bean实例创建和销毁时被调用。用户可以实现这些接口中定义的方法,Spring会在适当的地方调用它们。还有一个是FactoryBean,它是一个特殊的Bean,这个Bean可以被用户更多地控制

IOC容器如何为我所用

使用Spring必须要首先构建Ioc容器,没有它Spring就无法工作,ApplicationContext.xml就是Ioc容器默认的配置文件,Spring的特性都是基于Ioc容器工作的,包括AOP

想要扩展Spring就需要通过上述的IOC的扩展点,通过实现这些扩展点来改变Spring的通用行为,得到我们想要的个性化结果

Spring的AOP特性说明

动态代理就得先说明JDK的动态代理了,在JDK的java.lang.reflect包下有一个Proxy类,它正是构建代理类的入口,这个类有一个newProxyInstance方法就是构建代理对象的方法。这个方法需要3个参数:

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

构建代理类是在sun.misc.ProcyGenerator类的generateProxyClass方法中进行的

构建出的代理类是类似$ProxyXXX这样的类名,在这个类中会有被代理类的所有方法以及Object类的hashCode,equals,toString方法,同时还会有一个java.lang.reflect.Method类型的属性mXXX与每个方法对应。在这些方法里面都会调用InvocationHandler的invoke方法,每个与之对应的属性变量m会被传给invoke方法中的Method参数,这样就实现了代理

Spring AOP的实现

代理的目的就是调用目标方法时可以转为执行InvocationHandler接口的invoke方法,所以如何在InvocationHandler上做文章就是Spring实现AOP的关键

继承了FactoryBean的ProxyFactoryBean就是用于创建代理对象。创建出代理对象后,当调用目标对象上的方法时,都会被代理到InvocationHandler类的invoke方法中执行。JdkDynamicAopProxy类实现了InvocationHandler接口。

这是基于JDK的动态代理,Spring还支持一种基于子类的CGLIB代理。Spring AOP这里不仅使用了代理模式,因为涉及到JDK动态代理和CGLIB动态代理的切换,所以采用了策略模式

posted @ 2021-02-21 16:13  OverZeal  阅读(145)  评论(0编辑  收藏  举报