使用過Spring AOP的注解方式實(shí)現(xiàn)歇式,也入過不少坑每强,現(xiàn)在做一下記錄逻住,希望有同樣需求的朋友可以少走彎路
使用之前還是先過一下官方文檔吧创葡,至少可以少走彎路,不用擔(dān)心英文讀不懂唠叛,其實(shí)只看代碼例子就能理解很多問題只嚣!
1. SpringBoot如何獲得Aspect支持?
2. 我按照上面的方法開啟了AOP支持艺沼,為什么始終是不走切入點(diǎn)方法呢册舞?
首先仔細(xì)檢查一下,Aspect類是不是少了@Component
注解(這一點(diǎn)很重要障般!)调鲸,只有一個(gè)@Aspect
注解是不行的。如果還是不行挽荡,請(qǐng)繼續(xù)往下看藐石。
3. 攔截指定注解的規(guī)則怎么寫?如攔截所有帶了RequestMapping
的方法
首先聲明一個(gè)寫入點(diǎn)來匹配所有要攔截的方法名
假如攔截所有方法
@Pointcut("execution(public * *(..))")
private void aspectMethod(){}
然后配置通知方法
@Before(value = "aspectMethod() && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
public String doSomething() {
}
4. 攔截指定參數(shù)名的規(guī)則該怎么寫定拟?如攔截所有方法參數(shù)中有int page
的方法
參數(shù)攔截可以用
args
或@args
于微,但是匹配的時(shí)候跟順序和數(shù)量有關(guān)!
- 如果只有
page
一個(gè)參數(shù)
@Before(value = "aspectMethod() && args(page)")
public String doSomething(int page) {
}
- 如果
page
為第一個(gè)參數(shù)
@Before(value = "aspectMethod() && args(page, ..)")
public String doSomething(int page) {
}
- 如果
page
為第二個(gè)參數(shù)
@Before(value = "aspectMethod() && args(*, page, ..)")
public String doSomething(int page) {
}
說明:
- 參數(shù)的配置可以用占位符
*
和..
青自。
*
的意思是任意類型任意名稱的一個(gè)參數(shù)
..
的意思是任意類型角雷,任意多個(gè)參數(shù),并且只能放到args的后面性穿。- 通知方法的參數(shù)需要跟args中的固定參數(shù)
page
一致!- 如果要獲取攔截方法的所有參數(shù),可以用
JoinPoint
或ProceedingJoinPoint
雷滚,兩者的區(qū)別:
JoinPoint
是父類需曾,提供獲取攔截方法的信息的功能,如所有參數(shù):jp.getArgs()
ProceedingJoinPoint
是子類祈远,只能用在@Around
中呆万,除了提供JoinPoint
的所有功能外,還能提供方法的運(yùn)行pjp.proceed()
和pjp.proceed(args)
功能车份。
那下面問題來了谋减?我想匹配page參數(shù),但是page參數(shù)的位置不定怎么辦扫沼?
spring aop并不存在一個(gè)或多個(gè)的匹配出爹,所以如果可能庄吼,盡量將配置作為第一個(gè)參數(shù),這樣寫起來方便严就,如果真的需要匹配不確定的位置总寻,那就多寫幾個(gè)匹配規(guī)則吧!
- 第一個(gè)參數(shù):
args(page, ..)
- 第二個(gè)參數(shù):
args(*, page, ..)
- 第三個(gè)參數(shù):
args(*, *, page, ..)
- 以此類推
如果這樣還沒有滿足所有需求梢为,那么只能問問自己渐行,編碼的時(shí)候知道不知道什么叫約定大于配置
了。
5. 如果即有攔截參數(shù)铸董,又需要注入JoinPoint
或ProceedingJoinPoint
怎么辦祟印?
將JoinPoint
或ProceedingJoinPoint
作為第一個(gè)參數(shù),剩下的自定義的參數(shù)放到后面粟害,如:
@Before(value = "aspectMethod() && args(page)")
public String doSomething(JoinPoint jp, int page) {
}
6. 有沒有配置攔截規(guī)則示例蕴忆?
有的,請(qǐng)查看原文:aop pointcuts examples我磁。
這里注意孽文,
*
用在返回值和方法參數(shù)上并不是一個(gè)或多個(gè),而是指任意一個(gè)夺艰,如用在返回值上芋哭,表示任意類型的返回值;用在方法的參數(shù)上郁副,指任意類型的一個(gè)參數(shù)减牺。官方也給出了解釋,在這里可能會(huì)有很多坑存谎,大家可以注意一下拔疚!