Spring Ioc&Aop

引言

控制反转,面向切面都是程序设计当中比较成熟和有用的概念,它对于高内聚低耦合,添加新功能等都是非常成熟的设计方案,在Java中尤其以Spring框架对于其实现较为成熟,故在此探讨下其原理。

Spring Aop

Aop代理其实是由AOP框架动态生成的一个对象,即代理对象。AOP代理包含了目标对象的全部方法,但AOP代理中的方法与目标对象的方法存在差异:AOP方法在特定切入点添加了增强处理,并回调了目标对象的方法。
AOP代理所包含的方法与目标对象的方法示意图

首先对目标对象以及拦截器进行正确的配置,以便aopProxy代理对象的产出,主要是通过配置proxyfactorybean的属性来完成或者使用proxyfactory来实现,proxyfactorybean使用getObject作为入口方法,首先对通知链进行初始化,通知链封装了一系列的拦截器,拦截器通过从配置文件中读取,然后为代理对象的生成做准备。
SpringAop通过aopProxyFactory作为aopProxy代理对象的生产工厂,由它来负责产生相应的aopProxy代理对象,默认使用defaultAopFactory来生产对象,它决定了aopProxy代理对象的生产策略,(jdk的proxy或者gclib),aopProxy对象的产生最后委托给jdkdynamicAOPproxy或者cglib2proxy工厂来完成。
aopproxy代理对象拿到后,在代理的接口方法被调用的时候,并不是直接运行目标对象的调用方法,而是根据proxy机制,改变原有的目标对象方法调用的运行轨迹。首先会触发对方法的调用进行拦截,这些拦截对目标调用的功能增强提供了工作空间,拦截过程在jdk的proxy代理对象中,是通过invoke方法完成,而gclib是由设置好的callback方法完成的。
proxyfactorybean的回调中,首先会根据配置来对拦截器是否与当前调用的方法相匹配进行判断,如果当前调用的方法与配置的拦截器相匹配,那么相应的拦截器就会发挥作用,这个过程是一个遍历过程,会遍历在proxy代理对象中设置的拦截器链的所有拦截器。经过这个过程后,代理对象中定义好的拦截器链中的拦截器会被逐一调用,直到整个拦截器的调用完成。在拦截器调用完成之后,然后对目标对象进行方法调用。

Spring Ioc

Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean。
首先必须谈一谈Beandefinition,Beandefinition为管理bean之间的依赖关系提供了帮助只要遵循spring的定义规则来提供bean定义信息,我们可以使用各种形式的bean定义信息,比较常用的是使用xml文件格式。在初始化ioc容器 的过程中,首先要定位到bean的定义信息,spring使用resource接口来统一了bean的定义信息,而定位则通过 resourceLoader来完成,如果使用上下文,applicationcontext由于本身是defaultresourceLoader的子类, 为用户提供了定位功能,如果是使用beanfactory作为ioc容器的话,客户需要为beanfactory制定响应的resource来完成bean信息的定位。
容器初始化,如果使用上下文的话,需要一个对上下文进行初始化的过程,完成初始化以后,才能使用ioc容器
这个过程是通过构造函数的中调用refresh方法实现,refresh方法相当于就是容器的初始化函数,在初始化的
过程中,主要是要对beandefinition信息进行载入和注册工作,就是要在ioc容器当建立一beandefinition定义的数据映像,spring把载入功能从ioc容器中分离了出来,通过beandefinitionReader完成bean定义信息的读取,解析和ioc容器内部beandefinition的建立,在defaultListablebeanfactory中beandefintion被维护在hashmap中,ioc容器的bean管理和操作就是通过beandefinition来完成。
在容器初始化完成之后,但初始化只是在ioc容器内部建立了beandefinition,具体的依赖关系还没有注入,
容器在用户第一次向ioc容器请求bean时,ioc容器对相关的bean依赖进行注入,如果需要提前注入,可以通过
lazy-init属性进行预初始化(也是上下文初始化的一部分,起到提前完成依赖注入的控制作用),在依赖注入
完成之后,ioc就会保持这些具备依赖关系的bean供用户直接使用,通过getbean来获得bean,

依赖注入主要通过createbeanInstance和populatebean这两个方法,

createbeanInstance 主要是根据beandefintion来生成

bean所包含的对象,可以通过工厂方法、构造函数或者autowire进行实例化。构造函数有两种实例化策略,
一是通过beanUtils,利用jvm的反射功能,二是利用gclib来生成。
在初始化bean对象之后,就需要把依赖关系设置好,主要是对bean对象的属性的处理过程。
这个过程是在populatebean中委托beandefinitionResolver对beandefinition进行解析,通过beanwrapper的setProertyValues方法然后注入到property中。
在bean的创建和对象依赖注入中,需要通过依据beandefinition中的信息来递归的完成依赖注入,一个是
在上下文体系当中查找需要的bean和创建bean的递归调用。另一个就是在依赖注入的的时候,递归的调用
容器的getbean方法,得到当前Bean的依赖bean,同时触发了对依赖bean的创建和注入。在对bean的属性
进行依赖注入的时候,解析的过程也是递归的过程。

————没有什么是停不下来的,除了时间
validate