通配符
* 匹配任意數量字符
//任意返回值,任意名稱,任意參數的公共方法
execution(public * *(..))
//匹配com.zejian.dao包及其子包中所有類中的所有方法
within(com.zejian.dao..*)
+ 匹配給定類的任意子類
//匹配實現了DaoUser接口的所有子類的方法
within(com.zejian.dao.DaoUser+)
.. 匹配任意數量參數,任意數量包.
//匹配com.zejian.service包及其子包中所有類的所有方法
within(com.zejian.service..*)
//匹配以set開頭,參數爲int類型,任意返回值的方法
execution(* set*(int))
execution關鍵字
方法簽名表達式,語法如下:
execution(<scope> <return-type> <fully-qualified-class-name>.function(parameters))
參數解釋:
scope :方法作用域。如public、private、protect;不寫默認所有方法
returnt-type:方法返回值類型。*代表所有返回類型
fully-qualified-class-name:方法所在類的完全限定名稱。.. 表示包及所有子包
function:切入函數名稱。*表示所有名稱函數
parameters 方法參數。.. 表示所有類型以及個數參數
如:
@Pointcut("execution(* aop..*.*(..))") 可以匹配aop包及其子包下任意類的具有任意返回類型且包含任意參數的任意函數
within關鍵字
方便按照類型(如接口、類、包)過濾,語法格式:within(<type name>)
type name 使用包名或者類名代替
如:
@Pointcut("within(dao..*)") 可以匹配dao包及其子包中所有類中的所有方法
其他指示符
bean:匹配特定名稱的Bean對象的執行方法
//匹配名稱中帶有後綴Service的Bean。
@Pointcut("bean(*Service)")
this:匹配當前AOP代理對象類型的執行方法
//匹配了任意實現了UserDao接口的代理對象的方法進行過濾
@Pointcut("this(com.zejian.spring.springAop.dao.UserDao)")
target:匹配當前目標對象類型的執行方法
//匹配了任意實現了UserDao接口的目標對象的方法進行過濾
@Pointcut("target(com.zejian.spring.springAop.dao.UserDao)")
@annotation:根據所應有的註解進行方法過濾@within:匹配所有持有制定註解類型內的方法;與within不同
//匹配使用了MarkerAnnotation註解的方法(注意是方法)
@Pointcut("@annotation(com.zejian.spring.annotation.MarkerAnnotation)")
五種通知函數
參數可選:
可以將匹配的方法相應參數或對象自動傳遞給通知方法,如
@Before(value="args(param)", argNames="param")
public void before(int param) {
System.out.println("param:" + param);
}
優先級:
同一切面內多個通知在同一個切點函數上執行:切點函數前的通知順序執行,切點函數後的通知逆序執行。
不同切面內多個通知在同一個切點函數上執行:切面實現Ordered接口,並重寫getOrder方法返回優先級。切點函數前的通知按照優先級順序執行,切點函數後的通知按照優先級逆序執行。
五種通知分別爲:
- 前置通知@Before
在目標函數執行前執行。joinPoint 參數,可以獲取目標對象的信息,如類名稱,方法參數,方法名稱等。@Before("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
public void before(JoinPoint joinPoint){
System.out.println("前置通知");
} - 後置通知@AfterReturning
該函數在目標函數執行完成後執行,並可以獲取到目標函數最終的返回值returnVal。必須通過returning = “returnVal” 註明參數的名稱而且必須與通知函數的參數名稱相同。@AfterReturning(value="execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))",returning = "returnVal")
public void AfterReturning(JoinPoint joinPoint,Object returnVal){
System.out.println("後置通知...returnVal ="+returnVal);
} - 異常通知@AfterThrowing
該通知只有在異常時纔會被觸發,並由throwing來聲明一個接收異常信息的變量@AfterThrowing(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",throwing = "e")
public void afterThrowable(Throwable e){
System.out.println("出現異常:msg="+e.getMessage());
}
- 最終通知@After
類似於finally代碼塊,只要應用了無論什麼情況下都會執行@After("execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))")
public void after(JoinPoint joinPoint) {
System.out.println("最終通知....");
} - 環繞通知@Around
既可以在目標方法前執行也可在目標方法之後執行,更重要的是環繞通知可以控制目標方法是否指向執行。ProceedingJoinPoint,通過該對象的proceed()方法來執行目標函數,proceed()的返回值就是環繞通知的返回值。@Around("execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("環繞通知前....");
//執行目標函數
Object obj= (Object) joinPoint.proceed();
System.out.println("環繞通知後....");
return obj;
}