Spring AOP 註解方式實現的一些“坑”
使用過Spring AOP的註解方式實現,也入過不少坑,現在做一下記錄,希望有同樣需求的朋友可以少走彎路
使用之前還是先過一下官方文件吧,至少可以少走彎路,不用擔心英文讀不懂,其實只看程式碼例子就能理解很多問題!
1. SpringBoot如何獲得Aspect支援?
2. 我按照上面的方法開啟了AOP支援,為什麼始終是不走切入點方法呢?
首先仔細檢查一下,Aspect類是不是少了@Component
註解(這一點很重要!),只有一個@Aspect
註解是不行的。如果還是不行,請繼續往下看。
3. 攔截指定註解的規則怎麼寫?如攔截所有帶了RequestMapping
的方法
首先宣告一個寫入點來匹配所有要攔截的方法名
假如攔截所有方法
@Pointcut("execution(public * *(..))")
private void aspectMethod(){}
然後配置通知方法
@Before(value = "aspectMethod() && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
public String doSomething() {
}
4. 攔截指定引數名的規則該怎麼寫?如攔截所有方法引數中有int page
的方法
引數攔截可以用
args
或@args
,但是匹配的時候跟順序和數量有關!
- 如果只有
page
一個引數
@Before(value = "aspectMethod() && args(page)")
public String doSomething(int page) {
}
- 如果
page
為第一個引數
@Before(value = "aspectMethod() && args(page, ..)")
public String doSomething(int page) {
}
- 如果
page
為第二個引數
@Before (value = "aspectMethod() && args(*, page, ..)")
public String doSomething(int page) {
}
說明:
1. 引數的配置可以用佔位符*
和..
。
*
的意思是任意型別任意名稱的一個引數
..
的意思是任意型別,任意多個引數,並且只能放到args的後面。
2. 通知方法的引數需要跟args中的固定引數page
一致!
3. 如果要獲取攔截方法的所有引數,可以用JoinPoint
或ProceedingJoinPoint
,兩者的區別:
JoinPoint
是父類,提供獲取攔截方法的資訊的功能,如所有引數:jp.getArgs()
ProceedingJoinPoint
是子類,只能用在@Around
中,除了提供JoinPoint
的所有功能外,還能提供方法的執行pjp.proceed()
和pjp.proceed(args)
功能。
那下面問題來了?我想匹配page引數,但是page引數的位置不定怎麼辦?
spring aop並不存在一個或多個的匹配,所以如果可能,儘量將配置作為第一個引數,這樣寫起來方便,如果真的需要匹配不確定的位置,那就多寫幾個匹配規則吧!
- 第一個引數: args(page, ..)
- 第二個引數: args(*, page, ..)
- 第三個引數: args(*, *, page, ..)
- 以此類推
如果這樣還沒有滿足所有需求,那麼只能問問自己,編碼的時候知道不知道什麼叫約定大於配置
了。
5. 如果即有攔截引數,又需要注入JoinPoint
或ProceedingJoinPoint
怎麼辦?
將JoinPoint
或ProceedingJoinPoint
作為第一個引數,剩下的自定義的引數放到後面,如:
@Before(value = "aspectMethod() && args(page)")
public String doSomething(JoinPoint jp, int page) {
}
6. 有沒有配置攔截規則示例?
這裡注意,
*
用在返回值和方法引數上並不是一個或多個,而是指任意一個,如用在返回值上,表示任意型別的返回值;用在方法的引數上,指任意型別的一個引數。官方也給出瞭解釋,在這裡可能會有很多坑,大家可以注意一下!