1 连接点
连接点是程度控制流中的事件,比如方法的调用、需要修改的域、要计算的表达式、要执行的发放的第几行等。
下面是Aspectj将要显示为连接点的事件:
- 对方法或构造函数的调用
- 方法、构造函数或者advice体的执行
- 对一个域的访问或修改
- 类和对象的初始化
- 异常处理的执行:(通过抛出异常,after()throwing advice 可以用来捕捉任何连接点退出的信息)
2 切入点
切入点用于选择连接点。它扮演过滤的角色,匹配符合其定义的连接点,阻塞所有其他的连接点。
例如,pointcut call(String toString())将匹配对名为toString、无参数且返回值为一个字符串的发放的调用。
Aspectj支持三种不同种类的切入点:
- 也是最重要的一类,匹配基于连接点(方法调用、异常处理的执行、类的静态发放初始化等)的连接点
- 匹配基于范围的连接点。如,引起连接点的代码是否存在于一个特定的包中?连接点是否发生那个给定操作的控制流中?
- 最后一类切入点匹配基于自身上下文信息的连接点。如,当前执行的对象是否是那个给定类型的实例。
切入点可以命名也可以匿名,命名切入点可以使代码更高效更清晰。使用关键字pointcut可以声明命名的切入点。pointcut声明可以出现在类和aspect中,但是不能在接口中。
pointcut声明的一般形式如下:
[visibility-modifier] pointcut name(parameterList) : PointcutExpr;
实例:
pointcut leakedException():dbExceptionHandler && !inPersistenceLayer();
3 advice
切入点是匹配连接点的谓词,而advice则是指定在这些连接点处做的动作。每个advice与一个切入点(命名的或者匿名的)关联,并指定在该切入点匹配的连接点之前、之后或周围想要执行的操作。advice声明可以包括参数,参数值可以在advice体中引用,其中参数值是由调用者显示传递的,而advice体中的参数值是由切入点提供的。
基本的advice声明的类型有before advice、after advice、around advice,如下所示:
before(ParameterList) : PointcutExpr{ ... };
after(ParameterList) : returning : PointcutExpr{ ... };
after(ParameterList : throwing : PointcutExpr{ ... };
Type around(ParameterList) : PointcutExpr{ ... };
匿名切入点示例:
after(Account acc, Money amount)returning :
execution(void Account.*(Money)) &&
args(amount) &&
this(acc){
acc.getStatement().recordTransaction(thisJoinPointStaticPart, amount);
如下等效:
pointcut accountUpdate(Account acc, Money amount) :
execution(void Account.*(Money)) &&
args(amount) &&
this(acc);
after(Account acc, Money amount) returning :
accountUpdate(acc, amount){
acc.getStatement().recordTransaction(thisJoinPointStaticPart, amount);
}
}
等效