Spring3开发实战 之 第三章:AOP开发(2)(四)

2014-11-24 08:36:49 · 作者: · 浏览: 5
==param:" + param);
}
切入点表达式execution(* test(*)) && args(param) :
(1)首先execution(* test(*))匹配任何方法名为test,且有一个任何类型的参数;
(2)args(param)将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型,即java.lang.String;如果匹配将把该被通知参数传递给通知方法上同名参数。
参数匹配的策略
1:可以通过“argNames”属性指定参数名 ,示例如:

java代码:
查看复制到剪贴板打印
@Before(value=" args(param)", argNames="param") //明确指定了
public void before1(String param) {
System.out.println("===param:" + param);
}
2:如果第一个参数类型是JoinPoint、ProceedingJoinPoint或JoinPoint.StaticPart类型,应该从“argNames”属性省略掉该参数名(可选,写上也对),这些类型对象会自动传入的,但必须作为第一个参数 。示例如:

java代码:
查看复制到剪贴板打印
@Before(value=" args(param)", argNames="param") //明确指定了
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}
3:如果“ class文件中含有变量调试信息”,Spring将可以使用这些方法签名中的参数名来确定参数名,示例如下:

java代码:
查看复制到剪贴板打印
@Before(value=" args(param)") //不需要argNames了
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}
4:如果没有“ class文件中含有变量调试信息”,将尝试自己的参数匹配算法,如果发现参数绑定有二义性将抛出AmbiguousBindingException异常;对于只有一个绑定变量的切入点表达式,而通知方法只接受一个参数,说明绑定参数是明确的,从而能配对成功 ,示例如下:
@Before(value=" args(param)")
public void before1(JoinPoint jp, String param) {
System.out.println("===param:" + param);
}
5:以上策略失败将抛出IllegalArgumentException。
处理参数

java代码:
查看复制到剪贴板打印
@Around("execution(List find*(..)) &&" +
"com.xyz.SystemArchitecture.inDataAccessLayer() && " + "args(accountHolderNamePattern)")
public Object preProcessQueryPattern(ProceedingJoinPoint pjp, String accountHolderNamePattern)
throws Throwable {
String newPattern = preProcess(accountHolderNamePattern);
return pjp.proceed(new Object[] {newPattern});
}
获取方法运行后的返回值

java代码:
查看复制到剪贴板打印
@AfterReturning(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
returning="retVal")
public void doAccessCheck(Object retVal) {
// ...
}
Advice执行的顺序
如果有多个通知想要在同一连接点运行会发生什么?Spring AOP 的执行通知的顺序跟AspectJ的一样。 在“进入”连接点的情况下,最高优先级的通知会先执行(所以上面给出的两个前置通知(before advice)中,优先级高的那个会先执行)。 在“退出”连接点的情况下,最高优先级的通知会最后执行。只需要记住通知是按照定义的顺序来执行的就可以了。
当定义在 不同的 切面里的两个通知都需要在一个相同的连接点中运行,那么除非你指定,否则执行的顺序是未知的。 你可以通过指定优先级来控制执行顺序。在Spring中可以在切面类中实现 org.springframework.core.Ordered 接口做到这一点。 在两个切面中,Ordered.getValue() 方法返回值较低的那个有更高的优先级。


java代码:
查看复制到剪贴板打印
声明一个切面 :


...



...

声明一个切入点 :

expression="execution(* com.xyz.myapp.service.*.*(..))"/>


在切面里面声明一个切入点和声明一个顶级的切入点非常类似:

java代码:
查看复制到剪贴板打印


expression="execution(* com.xyz.myapp.service.*.*(..))"/>
...


当需要连接子表达式的时候,'&'在XML中用起来非常不方便,所以关键字'and', 'or' 和 'not'可以分别用来代替'&', '||' 和 '!'。

java代码:
查看复制到剪贴板打印
声明通知Advice,Before Advice

pointcut="execution(* com.xyz.myapp.dao.*.*(..))"
method="doAccessCheck"/>
...

返回后通知(After returning advice)

pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>
...

java代码:
查看复制到剪贴板打印
抛出异常后通知(After throwing advice)

pointcut-ref="dataAccessOperation"
thowing="dataAccessEx"
method="doRecoveryActions"/>
...

后通知(After (finally) advice)

pointcut-ref="dataAccessOperation"
method="doReleaseLock"/>
...


Around通知

java代码:
查看复制到剪贴板打印

pointcut-ref="businessService"
method="doBasicProfiling"/>
...

通知的参数,可以通过 arg-names 属性来实现

java代码:
查看复制到剪贴板打印
pointcut="com.xyz.lib.Pointcuts.anyPublicMethod(