本篇主要讲述Spring AOP一些基本概念及使用等。
那么AOP是什么呢?我所理解的AOP,通俗的说,就是一段代码片段在不修改源码的情况下,动态地在源码前后织入另一段代码(通过代理模式),使之增强。
下面抛出一些基本性的概念:
AOP指一种程序设计范式,该范型以一种称为切面(aspect)的语言构造为基础,切面是一种新的模块化机制,用来描述分散在对象,类或方法中的横切关注点,切面横切于各个功能之上 。
连接点(Joinpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,在AOP中表示为“在哪里做”;
切入点(Pointcut):选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,在AOP中表示为“在哪里做的集合”;
增强(Advice):在连接点上执行的行为,增强提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置增强(before advice)、后置增强 (after advice)、环绕增强 (around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入增强 ;在AOP中表示为“做什么”;
方面/切面(Aspect):横切关注点的模块化,可以认为是增强、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为“在哪里做和做什么集合”;
目标对象(Target Object):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被增强的对象,从而也可称为“被增强对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为“对谁做”;
AOP代理(AOP Proxy):AOP框架使用代理模式创建的对象,从而实现在连接点处插入增强(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
织入(Weaving):织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。
引入(inter-type declaration):也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), 在AOP中表示为“做什么(新增什么)”;
AOP增强(Advice)的类型
前置增强(Before advice):
在某连接点(join point)之前执行的增强,但这个增强不能阻止连接点前的执行(除非它抛出一个异常)。
后置返回增强(After returning advice):
在某连接点正常完成后执行的增强:例如,一个方法没有抛出任何异常,正常返回。
后置异常增强(After throwing advice):
在方法抛出异常退出时执行的增强。
后置最终增强(After (finally) advice):
当某连接点退出的时候执行的增强(不论是正常返回还是异常退出)。
环绕增强(Around Advice):
包围一个连接点的增强,如方法调用。这是最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
举个例子,假如我们要对项目中所有的 *Update() 方法前添加打印入参的日志,那么在这里,所有的 *Update() 方法即构成切入点,而其中某个具体的方法就是连接点,打印入参的代码即增强,在方法前打印入参日志就是在连接点上执行增强,这一实现就是织入。增强和切入点构成了切面,织入就是将切面应用到目标对象。通常我们使用创建的对象调用其实例方法,而在AOP中则需要使用代理对象。一个例子:同一个类中有两个实现了AOP的方法A、B,在方法A内部调用了B,而执行方法A之后却能发现只有A的切面实现了,而B没有
public class AB{
public void A() {
//A方法业务
B();
}
public void B() {
//B方法业务
}
}
这是因为调用方法A的是代理对象,而在方法A内部调用方法B的则是AB的实例。在使用 Spring AOP 的时候,我们从 IOC 容器中获取的Bean其实都是代理对象,而不是那些 Bean对象本身。当在方法A内部调用方法B时,其实等价于 this.B(); 而this 关键字引用是这个对象的本身,因而 Spring AOP 是不能拦截到这个方法A内部的B方法 。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
在Spring AOP中,我们在<aop:config></aop:config>中定义<aop:aspect></aop:aspect>(切面),<aop:aspect>标签内进一步定义<aop:pointcut></aop:pointcut>(切入点),<aop:before>、<aop:after>等增强。此外还有 <aop:declare-parents>表示引入, Advisors用来定义只有一个增强和切入点的切面。具体配置就暂不写了。。。http://chouyi.iteye.com/blog/1670749 这篇文章有具体的列出可供参考。
以上部分知识点参考http://jinnianshilongnian.iteye.com/blog/1418596