面向切面编程AOP
AOP的作用是分离掉实现对象方法时不需要关注的功能,或者在无法修改源码的情况下,给对象增加功能。例如日志、安全和事务管理功能在软件中很重要,但是在编写程序时主动将这些功能加入对象中又十分麻烦,就可以利用AOP简化难度了。
AOP术语
通知(Advice)定义了切面必须完成的工作和什么时候完成。根据完成的时机,分为五种:Before, After, After-returning, After-throwing, Around。简答理解这些通知时机,before即在执行切面前,after在执行切面后。那after-returning和after有什么区别?如果关心切面返回的结果,使用前者,如果只是简单的定义一下执行完后需要做的工作,使用后者。After-throwing定义抛出错误后需要执行的工作。Around称为环绕,一开始不能理解它与同时使用before和after的区别,后来了解到,对于before和after,不方便进行消息传递和信息共享,如果涉及到消息传递的情况,则around是一个不错的选择。对于@Around注解,需要在通知方法中注入ProceedingJoinPoint对象,这样调用jp.proceed()可以调用被通知的方法,从而决定被通知的方法到底何时调用。
连接点(join point)定义了应用通知的时机。举个简单的例子,通知x需要在对象n的f功能执行前调用,那么这个f就是连接点。
切点(pointcut)定义会匹配通知所要织入的一个或多个连接点。简单来说切点用于缩小切面所统治的连接点的范围。
切面(aspect)是通知和切点的结合,在何时何处完成何种工作。
引入(introduction)表示向已有的类中添加新的方法或属性。通常使用代理实现。
织入(weaving)表示把切面应用到目标对象并创建新的代理对象的过程。
切点的例子
以《Spring实战》中音乐会为例子。
@Aspect
public class Audience {
@Before(“execution(** concert.Performance.perform(..))”)
public void foo() {
//do something
}
}
其中@Aspect注解定义了切面应用于Audience对象上,@Before标注表示通知应用在perform调用之前,其中的语句进行解析,**表示不论方法返回的值,concert.Performance.perform定义了具体的方法,..表示不论方法传入的参数。定义在通知中的语句,还可以进行与&&,或||,非!等操作。通过对该语句的解析,可以得到推论,即使用不同方法签名确定某个特定的方法。
当然,如果对perform调用的之前之后都有定义通知,可以使用
@Pointcut(“execution(** concert.Performance.perform(..)”)
public void performance() {}
来定义切点简化操作。即传入通知注解的语句可以简化为”performance()”。
引入的例子
@Aspect
public class EncoreableIntroducer {
@DeclareParents(value=“concert.Performance+”, defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
value指定了哪种类型的bean需要引入该接口,+表示该类型的子类。
defaultImpl指定了引入接口提供实现的类。
标注的静态Encoreable表示要引入的接口为Encoreable。