Spring AOP切面實現:引數傳遞
通知方法引數注入:
在Spring AOP中,除了execution和bean指示符不能傳遞引數給通知方法,其他指示符都可以將匹配的相應引數或物件自動傳遞給通知方法。
1、獲取匹配的引數
通過"argNames"屬性指定引數名。
@Before(value="args(param)", argNames="param") //明確指定了
public void beforeTest(String param) {
System.out.println("param:" + param);
}
args、argNames的引數名與beforeTest()方法中引數名 保持一致,即param
使用args指示符,可以不利用argNames宣告引數
@Before("execution(public * com.learn..*.show(..)) && args(userId,..)")
public void beforeTest(int userId) {
System.out.println("userId:" + userId);
}
args的引數名與beforeTest()方法中引數名 保持一致,即param
2、獲取匹配的物件
例:
Table是一個自定義註解。要獲取該物件,annotationTest方法要先在方法中定義新增該引數,再利用argNames宣告,切入點表示式也要改為引數名。即t@Pointcut(value="@annotation(t)",argNames = "t") public void annotationTest(Table t) { } //引用時帶上類名 @After(value = "annotationTest(t)") public void after(Table t) { System.out.println("呼叫LearnAspect的切入點pointcut()"); }
JoinPoint獲取引數:
Spring AOP提供使用org.aspectj.lang.JoinPoint型別獲取連線點資料,任何通知方法的第一個引數都可以是JoinPoint(環繞通知是ProceedingJoinPoint,JoinPoint子類)。
(1)JoinPoint:提供訪問當前被通知方法的目標物件、代理物件、方法引數等資料
(2)ProceedingJoinPoint:只用於環繞通知,使用proceed()方法來執行目標方法
如引數型別是JoinPoint、ProceedingJoinPoint型別,可以從“argNames”屬性省略掉該引數名(可選,寫上也對),這些型別物件會自動傳入的,但必須作為第一個引數。
例:
切面:
@Pointcut(value="args(p)")
public void argsTest(int p)
{
}
@Before(value="argsTest(p)",argNames="p")
public void afterTest(JoinPoint jp,int p)
{
Object[] o = jp.getArgs();
System.out.println(o[0]);
System.out.println(p);
System.out.println("args");
}
結果:
1 //利用JoinPoint獲取引數
1 //利用引數注入獲取引數
args
This is showTime
AfterReturning 獲取請求返回值:
@Pointcut("execution(public * com.learn.spring..*.*(*))")
public void pointcut() {
}
/*
*配置後置通知返回,使用在方法pointcut()上註冊的切入點
*/
@AfterReturning(pointcut="pointcut()", returning="returnValue")
public void afterReturn(Object returnValue)
{
System.out.println("afterReturn "+returnValue);
}
注意:
1、returning引數名與afterReturn()方法引數名相同,即都為returnedValue.
2、AfterRetruning含有返回值時,不能和Around指示符使用同一個pointcut。返回值會為null,報錯:
org.springframework.aop.AopInvocationException:
Null return value from advice does not match primitive return type for: ....
AfterThrowing 獲取請求丟擲異常:
@Pointcut("execution(public * com.learn.spring..*.*(*))")
public void pointcut() {
}
/*
* 配置丟擲異常後通知,使用在方法pointcut()上註冊的切入點
*/
@AfterThrowing(pointcut="pointcut()",throwing="ex")
public void afterThrow(Exception ex)
{
System.out.println("afterThrow "+ex.getMessage());
}
throwing引數名與afterThrow()方法引數名相同,即ex