SpringAOP中@annotation與execution的深度示例對(duì)比分析
在 Spring AOP 中,@annotation 和 execution 是兩種常用的切點(diǎn)表達(dá)式(Pointcut Expression),用于定義哪些方法需要被切面(Aspect)攔截。它們的設(shè)計(jì)目的、匹配規(guī)則和適用場景有顯著區(qū)別,以下從核心機(jī)制、語法、應(yīng)用場景和示例進(jìn)行對(duì)比分析:
?? ?一、核心概念與機(jī)制?
1. ?**@annotation表達(dá)式**?
- ?作用?:匹配帶有特定注解的方法。
- ?原理?:基于方法上的注解標(biāo)記進(jìn)行攔截,與方法的簽名(類名、方法名等)無關(guān)。
- ?適用場景?:
- 需要為特定功能?(如日志、權(quán)限校驗(yàn))標(biāo)記方法時(shí)。
- 需通過注解傳遞元數(shù)據(jù)(例如
@Permission(role="admin"))。
- ?優(yōu)點(diǎn)?:靈活性高,與業(yè)務(wù)邏輯解耦,適合自定義橫切關(guān)注點(diǎn)。
- ?缺點(diǎn)?:需顯式在方法上添加注解,無法批量匹配無注解的方法。
2. ?**execution表達(dá)式**?
- ?作用?:通過方法簽名?(返回值、包名、類名、方法名、參數(shù)類型)匹配方法。
- ?原理?:基于方法的結(jié)構(gòu)特征攔截,無需方法添加額外注解。
- ?適用場景?:
- 批量攔截特定包/類下的所有方法?(如
com.example.service.*.*(..))。 - 按命名規(guī)范匹配方法(如所有
update*開頭的方法)。
- 批量攔截特定包/類下的所有方法?(如
- ?優(yōu)點(diǎn)?:無需修改代碼,適合通用功能(如接口耗時(shí)統(tǒng)計(jì))。
- ?缺點(diǎn)?:表達(dá)式復(fù)雜,對(duì)無規(guī)則的方法難以精確匹配。
?? ?二、語法詳解?
1. ?**@annotation語法**?
@Before("@annotation(com.example.Loggable)")
public void logBefore(JoinPoint joinPoint) {
// 通知邏輯
}- ?參數(shù)?:注解的全限定類名(如
com.example.Loggable)。 - ?擴(kuò)展?:可與自定義注解結(jié)合,實(shí)現(xiàn)動(dòng)態(tài)控制(例如
@Loggable(level="DEBUG"))。
2. ?**execution語法**?
@Around("execution(* com.example.service.*.*(..))")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
// 環(huán)繞通知邏輯
}- ?結(jié)構(gòu)?:
execution(修飾符? 返回值 包.類.?方法名(參數(shù)) 異常?)*:通配任意元素(如返回值、單層包名)。..:通配多層包或任意參數(shù)(如com..*.ServiceImpl匹配com下所有子包的ServiceImpl類)。
- ?示例?:
- 匹配
UserService的所有方法:execution(* com.service.UserService.*(..)) - 匹配所有
save開頭的方法:execution(* save*(..))
- 匹配
?? ?三、典型場景對(duì)比?
| ?維度? | ?**@annotation**? | ?**execution**? |
|---|---|---|
| ?匹配依據(jù)? | 方法上的注解標(biāo)記 | 方法簽名(包、類、方法名、參數(shù)等) |
| ?代碼侵入性? | 需在方法上添加注解 | 無侵入,直接匹配方法結(jié)構(gòu) |
| ?靈活性? | 高(可通過注解參數(shù)定制邏輯) | 中(依賴方法命名和包結(jié)構(gòu)) |
| ?適用案例? | - 權(quán)限校驗(yàn)(@RequireAuth)- 日志分級(jí)( @LogLevel("DEBUG")) | - 接口耗時(shí)統(tǒng)計(jì) - 全局事務(wù)管理 - 包級(jí)別異常處理 |
| ?復(fù)雜匹配能力? | 弱(僅依賴注解是否存在) | 強(qiáng)(支持通配符、邏輯運(yùn)算符組合) |
?? ?四、代碼示例?
1. ?**@annotation實(shí)現(xiàn)自定義日志**?
// 自定義注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {}
// 切面類
@Aspect
@Component
public class LogAspect {
@Before("@annotation(com.example.Loggable)")
public void logMethodCall(JoinPoint jp) {
System.out.println("Log: " + jp.getSignature().getName());
}
}
// 業(yè)務(wù)方法使用
@Service
public class UserService {
@Loggable
public void createUser() { ... }
}2. ?**execution實(shí)現(xiàn)方法耗時(shí)統(tǒng)計(jì)**?
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature() + " executed in " + duration + "ms");
return result;
}
}? ?五、如何選擇???
- ?優(yōu)先
@annotation?:
當(dāng)需要精細(xì)控制且邏輯與業(yè)務(wù)無關(guān)時(shí)(如權(quán)限、審計(jì)日志),通過注解實(shí)現(xiàn)解耦。 - ?優(yōu)先
execution?:
需批量攔截?(如全局性能監(jiān)控)或無法修改源碼時(shí),通過方法簽名覆蓋。 - ?混合使用?:
復(fù)雜場景可組合表達(dá)式,例如:
@Before("@annotation(com.example.Auth) && execution(* com.service.*.*(..))")?? ?總結(jié)?
- ?**
@annotation?:注解驅(qū)動(dòng),精準(zhǔn)標(biāo)記方法,適合高定制化橫切邏輯**。 - ?**
execution?:結(jié)構(gòu)驅(qū)動(dòng),無侵入匹配,適合通用功能增強(qiáng)**。
兩者本質(zhì)是互補(bǔ)工具,實(shí)際開發(fā)中需根據(jù)侵入性容忍度、匹配精度和維護(hù)成本綜合選擇。
到此這篇關(guān)于SpringAOP中@annotation與execution的深度對(duì)比的文章就介紹到這了,更多相關(guān)springaop @annotation與execution內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 方法泛型入?yún)和String的重載關(guān)系詳解
這篇文章主要介紹了java 方法泛型入?yún)和String的重載關(guān)系詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java中this關(guān)鍵字用法梳理詳細(xì)講解
this關(guān)鍵字是java常用的關(guān)鍵字,可用于任何實(shí)例方法內(nèi)指向當(dāng)前對(duì)象,也可指向?qū)ζ湔{(diào)用當(dāng)前方法的對(duì)象,下面這篇文章主要介紹了Java中this關(guān)鍵字用法梳理的相關(guān)資料,需要的朋友可以參考下2025-07-07
Java ThreadLocal詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
ThreadLocal,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲(chǔ),本文會(huì)詳細(xì)的介紹一下,有興趣的可以了解一下2017-06-06
Spring Boot中的YML配置列表及應(yīng)用小結(jié)
在Spring Boot中使用YAML進(jìn)行列表的配置不僅簡潔明了,還能提高代碼的可讀性和可維護(hù)性,這篇文章主要介紹了Spring Boot中的YML配置列表的詳細(xì)解析,需要的朋友可以參考下2025-05-05
SpringBoot將Spring fox更換為Springdoc的方法詳解
由于項(xiàng)目中使用Spring fox已經(jīng)不維護(hù)更新了,代碼掃描,掃出問題,需要將Spring fox更換為Spring Doc,所以本文給大家介紹了SpringBoot將Spring fox更換為Springdoc的方法,文中有相關(guān)的代碼供大家參考,需要的朋友可以參考下2024-01-01
如何使用java agent修改字節(jié)碼并在springboot啟動(dòng)時(shí)自動(dòng)生效
本文介紹了JavaAgent的使用方法和在SpringBoot中的應(yīng)用,JavaAgent可以通過修改類的字節(jié)碼,實(shí)現(xiàn)對(duì)非Spring容器管理對(duì)象的AOP處理,演示了如何定義切面邏輯,實(shí)現(xiàn)接口mock,感興趣的朋友跟隨小編一起看看吧2024-10-10
Java實(shí)現(xiàn)超市會(huì)員管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)超市會(huì)員管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

