您的位置:首页 > 编程语言 > Java开发

Spring揭秘:第七章-第十二章Spring AOP框架

2015-07-06 21:02 288 查看

一、AOP基础

AOP走到现在有两种实现形式:第一代为静态AOP时代,代表为AspectJ为杰出代表,它会使用ajc编译器将各个Aspect以Java字节码的形式编译到系统的各个功能模块中,以达到融合Aspect和Class的目的。它的优点是Aspect直接以Java字节码的形式编译到Java类中,Java虚拟机可以像通常一样加载Java类运行,不会对整个系统的运行造成任何性能损失。第二代动态AOP时代,通过JAVA语言提供的各种动态我来实现Aspect织入到当前系统的过程(Spring
AOP就是通过这种方式)。它的优点是用JAVA语言实现,更容易开发和集成,能更好的动态调整。缺点是会带来性能损失,大多数情况下,这种性能损失是可以容忍的。

(1)Joinpoint

将要在其之上进行织入操作的系统执行点就是称之为Joinpoint,常见的类型有:方法调用,方法调用执行,构造方法调用,构造方法执行,字段设置,字段获取,异常处理执行,类初始化。

(2)Pointcut

Pointcut概念代表的是Jointpoint的表述方式,将横切逻辑织入当前系统的过程中,参照Pointcut规定的Jointpoint信息,才可以知道应该往系统的哪些Jointpoint上织入横切逻辑。它的表述方式有:直接指定所在方法名称,正则表达式,使用特定的Pointcut表达语言。它还支持一定的逻辑运算,比如与,或。

(3)Advice

Advice是单一横切关注点逻辑的载体,它代表将会织入到Joinpoint的横切逻辑。其形式有:1、Before Advice,在Joinpoint指定位置之前执行的Advice类型。2、After Adivce,在连接点之后执行的类型。还可细分为After retunrn Advice(返回处),After throwing Advice(catch处),After Advice(类似finally处)。3、Around Advice,对Joinpoint进行包裹,可以在Joinpoint之前和之后都指定相应的逻辑,甚至于中断或者忽略Joinpoint处原来程序流程的执行。4、Introduction,可以为原有的对象添加新和特性或行为。

(4)Aspect

Aspect是对系统中的横切关注点逻辑进行模块化封装的AOP概念实体,通常情况下,Aspect可以包含多个Pointcut以及相关Advice定义。

(5)织入和织入器

AspectJ有专门的编译器来完成织入操作,即ajc。Spring AOP使用一组类来完成最终的织入操作,最通用的织入器是ProxyFactory。

二、Spring AOP初探

动态代理机制的根源——代理模式。

动态代理机制的实现主要由一个类和一个接口组成,即java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口(实现目标对象存在接口时的情况)。而当要通过继承的方式来扩展对象定义,则需要借助CGLIB这样的动态字节码生成库,在系统运行期间动态地为目标对象生成相应的扩展子类。

三、Spring AOP一世

SpringAOP中对于Joinpoint的支持仅限于方法执行。而Spring AOP中的Pointcut对象中,getClassFilter()方法返回的ClassFilter对象完成class级别的类型匹配,getMethodMatcher()方法返回的methodMatcher对象完成方法匹配以及方法中参数的调用。

常见的Pointcut有:
(1)NameMatchMethodPointcut:直接匹配方法名。
(2)JdkRegexpMethodPointcut(JDK1.4以上支持)和Perl5RegexpMethodPointcut(无JDK版本限制):用于正则表达式匹配方法名,注意,使用正则表达式匹配相应的Jointpoint所处的方法时,正则表达式的匹配模式必须以匹配整个方法签名(Method
Signature)的形式指定。那么使用正则表达式.*doSth.*则会匹配任意包下的的doSth方法。
(3)AnnotationMatchingPointcut(JDK1.5以上):利用注解进行匹配
(4)ComposablePoint:逻辑运算匹配
(5)ControlFlowPoint:织入特定类实例的方法。性能较差,如果不是十分必要,避免使用。
Spring中的Advice实现全部遵循AOP Alliance规定的接口。
per-class类型的Advice是指,该类型的Advice的实例可以在目标对象类的所有实例之间共享。这种类型的Advice通常只是提供方法拦截的功能,不会为目标对象类保存任何状态或者添加新的特性。接口有:BeforeAdvice(在Jointpoint之前执行),ThrowsAdvice(在抛出异常后执行),AfterReturningAdvice(可以访问当前Jointpoint的方法返值,方法,方法参数以及所在的目标对象,但不能修改返回值),AroundAdvice(Spring中的接口为Interceptor,可以修改返回值,前几种Advice能完成的任务都可以完成)。
per-instance类型的Advice不会在目标类所有对象实例之间共享,而是会为不同的实例对象保存它们各自的状态及相关的逻辑,常用于为目标类添加新的属性及行为。在Spring
AOP中,Introduction就是唯一的一种per-instance型Advice。



Introduction由于采用的是动态代理机制,性能上要逊色不少。
Spring AOP中的Aspect——Advisor通常只持有一个Pointcut和一个Advice.



在PointcutAdvisor常用实现有DefaultPointcutAdvisor,NameMatchMethodPointcutAdvisor,RegexpMethodPointcutAdivsor(可以根据命令看出这些类对pointcut类型的限制,不过NameMatchMethodPointcutAdvisor不能使用Introduction类型的Advice),DefaultBeanFactoryPointcutAdvisor(自身绑定到了BeanFactory,需绑定工程兵IoC容器中)。
IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advisce.
Order接口用来保证各个Advisor的运行顺序。
Spring AOP 的织入
ProxyFactory并非是Spring AOP唯一可用的织入器,不过是最基本的一个织入器实现。它的运行需要传入两个最基本的东西:进行织入的目标对象,将到应用到目标对象的Aspect,即Spring中的Advisor。Spring
AOP在使用代理模式实现AOP的过程中采用了动态代理和CGLIB两种机制,分别对实现了某些接口的目标类和没有实现任何接口的目标类进行代理,当然也可以设置让有接口的目标类采用CGLIB机制。
以下是相关结构图。





首先,在ProxyConfig中记载生成代理对象的控制信息,而Advised记载生成代理对象所需要的必要信息。其中Proxyconfig中有5个boolean属性:其中proxyTargetClass,optimize(该值 还告知是否采取优化)控制是否使用CGLIB代理对象生成。opaque用于控制生成代理对象是否可以强制转型为Advised。exposeProxy生成代理对象是否绑定在ThreadLocal。frozen代生成的信息配置完成后是否允许更改。
Aopproxy有cglib2AopProxy和JdkDynamicAopProxy两种实现,它们的实例化采用工厂模式(抽象工厂模式)进行封装,即通过AopProxyFactory实现,该工厂接收AdviseSupport来决定生成什么类型的Aopproxy。
实际情况中,以上类的关系发上图ProxyCreatorSupport继承AdvisedSuppord,拥有生成代理对象的必要信息,内部又持有AopproxyFactory实例。ProxyFactory集AopProxy和AdvisedSupport于一身,可以完全实现两者的职责——设置代理对象信息,生成代理对象。其中一个特殊的织入器是容器中的织入器——ProxyFactoryBean,可以在IoC容器在直接生成代理对象。



不过,在IoC窗口中使用ProxyFactoryBean都是针对每个目标对象,然后给出它们各自就的ProxyFactoryBean配制,当
目标对象很多时,需要的是自动代理(AutoProxy)机制。
这一过程的实现建立在IoC容器的BeanPostProcessor概念之上。常用的AutoProxyCreator即BeanNameAutoProxyCreatorT和DefaultAvisorAutoProxyCreator(更自动化,会
直接搜索容器内的Advisor)。
TargetSource的作用类似在目标对象在外面加了一个壳,当要调用目标对象上定义的方法时,不是直接调用目标对象的方法,而是通过Targetsource来取得目标对象,再调用
从TargetSource中取得的目标对象上的相应方法。通常情况下,无论是通过setTarget(),还是通过setTargetName()等方法设置的目标对象,框架内部都会通过一个TargetSou
rce实现类对这个设置的目标对象进行封装。它提供一个目标对象池,每次从TargeSouce取得目标对象都从这个目标对象池中取得。让一个TargeSource实现类持有多个目标对
象实例,然后按照某种规则,在每次方法调用时,返回相应的目标对象实例。它的实现类有:(1)singletonTArgetSource(只持有一个目标对象实例)(2)PrototypeTarge
Source(每次返回一个新的对象实例)(3)HotSwappableTargetSource(根据需要替换持有对象)(4)CommonsPoolTargetSource(返回有限数目的目标对象实例)(5)Thr
eadLTargetSource(为不同对象返回不同的目标对象实例,是对JDK标准的ThreadLocal的简单封装)

四、Spring AOP二世

这是Spring框架2.0发布后,新增的特性或者说新的使用方式。用用注解的方式,是对原有的AOP方法的一种新的使用方式,也扩展了一些功能,但使用的依然是Spring1.x
原先的实现体系。
Pointcut的标志符;1,execution方法匹配2,within类型匹配3,args参数匹配
Advice并没有太多变化。
要注意的是对Order接口的实现只对IOC容器注册并使用的Aspect有效,如果是通过编程方式来使用这些Aspect,Advice的执行顺序完全由添加的顺序决定。
基于Schema AOP是另一种新增的AOP使用方式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: