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容器来说,,主要有后置处理器BeanFactoryPostProcessor和BeanPostProcessor,它们分别在构建BeanFactory和构建Bean对象时调用。还有就是InitializingBean和DisposableBean,它们分别在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动态代理的切换,所以采用了策略模式