AOP(Aspect-Oriented Programming,面向切面编程)是对OOP的一个极大补充,但是AOP中各种概念实体却是有些复杂,尤其是对于刚接触AOP的人来说。但是为了使用AOP,为了理解AOP,这些实体又是迈步过去的坎,编程虐我千百遍,我待编程如初恋。我相信,用真心和努力终能感动它。AOP本身就没有一个统一的标准,不同的AOP实现都略有不同,再加上这些东西都是老外搞出来的,翻译到国内又造成了二次不统一,所以还是用英文表述这些概念更清晰一些。切来看
Joinpoint:在系统运行之前,AOP的功能模块都需要织入到OOP中,为了进行这种织入,我们需要知道在系统的哪些执行点上进行织入操作。Joinpoint就是织入时的点。一些常见的Joinpoint类型:
●方法调用(Method Call),某个方法被调用的时候所处的程序执行点;
●方法执行(Method Call execution),某个方法内部执行开始的点;注意与方法调用的区别,方法调用是在调用对象上的点,方法执行是被调用的方法逻辑执行时的点;
●构造方法调用(Constructor Call),构造方法执行(Constructor Call execution),与上面的两个类似;
●字段设置(Field Set),字段获取(Field Get),字段被设置或获取时的点;
●异常处理执行(Exception Handler Execution),在应用程序执行过程中,某些类型异常抛出后,对应的异常处理逻辑执行的时点;
●类初始化(Class initialization),静态类型,静态语句块执行时的点;
在程序的执行过程中,几乎所有的执行时点都可以称为Joinpoint,但是有些实现难度太大,效果却很一般。不同的AOP产品支持不同的Joinpoint,Spring目前只支持方法级别的Jointpoint,更具的的说是方法执行,这在大部分时间内都足够使用了。Spring在实现AOP时,很好的遵循了二八原则,花20%的代价实现80%的功能。
Pointcut:前面有了Jointpoint,但是我们必须理解,前面说的Jointpoint是切入点的类型,比如方法执行是一种Joinpoint,但是在实际织入的时候,我们还是应该指明在哪些类的哪些方法上执行织入。Pointcut是Joinpoint的表述方式,Pointcut规定了具体的Joinpoint。比如使用Pointcut来指定Jointpoint:类A的execute()方法被调用的所有的Joinpoint。在Spring中,使用正则表达式来指定Pointcut。
Advice:面向切面的编程就是在不改变源码的情况下,将横切逻辑(比如日志记录,安全检查)织入到系统中,Advice就是横切逻辑。按照Advice在Joinpoint位置执行时机的差异或者完成的功能不同,Advice可以分成一下几类:
●Before Advice:在Joinpoint指定位置之前执行的Advice;
●After Advice:在Joinpoint之后执行的Advice,它包括三类
(1)Joinpoint正常返回之后,After returning Advice
(2)Joinpoint抛出异常的情况下,After throwing Advice
(3)不管Joinpoint是正常执行,还是抛出异常都会执行,After Advice
关于After Advice三种类型的执行点如下图所示:
●Around Advice,在Joinpoint之前和之后都执定相应的逻辑,甚至可以中断或者忽略Joinpoint处原来的程序流程执行,这个功能最强大,应用最多。
●Introduction,为类添加一些属性和方法,这是一种特殊的Advice。
Aspect:AOP的概念实体,Aspect是Pointcut和Advice的模块化封装,它既包括了Advice的定义,也包括了Joinpoint的定义(包含的是Pointcut,因为Pointcut定义Joinpoint)。比如Spring就是负责将Aspect所定义的Advice织入到Aspect所定义的Joinpoint中。
织入:将Advice添加到Joinpoint上,Spring采用动态代理和CGLIB来完成织入。
目标对象:符合Pointcut所指定的条件,将在织入过程中被织入横切逻辑的对象。
以上对AOP中的各种实体进行了介绍,总结一下:AOP是面向切面的编程,其中Aspect就是切面,它包括了横切逻辑(Advice)和Pointcut,横切逻辑就是我们要添加的功能,而Pointcut则规定了在哪些地方(Jointpoint)执行这些添加的功能。