1. 程式人生 > >Spring AOP 註解方式實現的一些“坑”

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. 如果要獲取攔截方法的所有引數,可以用JoinPointProceedingJoinPoint,兩者的區別:
JoinPoint是父類,提供獲取攔截方法的資訊的功能,如所有引數:jp.getArgs()
ProceedingJoinPoint是子類,只能用在@Around中,除了提供JoinPoint的所有功能外,還能提供方法的執行pjp.proceed()pjp.proceed(args)功能。

那下面問題來了?我想匹配page引數,但是page引數的位置不定怎麼辦?
spring aop並不存在一個或多個的匹配,所以如果可能,儘量將配置作為第一個引數,這樣寫起來方便,如果真的需要匹配不確定的位置,那就多寫幾個匹配規則吧!
- 第一個引數: args(page, ..)
- 第二個引數: args(*, page, ..)
- 第三個引數: args(*, *, page, ..)
- 以此類推

如果這樣還沒有滿足所有需求,那麼只能問問自己,編碼的時候知道不知道什麼叫約定大於配置了。

5. 如果即有攔截引數,又需要注入JoinPointProceedingJoinPoint怎麼辦?

JoinPointProceedingJoinPoint作為第一個引數,剩下的自定義的引數放到後面,如:

@Before(value = "aspectMethod()  &&  args(page)")
public String doSomething(JoinPoint jp, int page) {
}

6. 有沒有配置攔截規則示例?

這裡注意,*用在返回值和方法引數上並不是一個或多個,而是指任意一個,如用在返回值上,表示任意型別的返回值;用在方法的引數上,指任意型別的一個引數。官方也給出瞭解釋,在這裡可能會有很多坑,大家可以注意一下!