SpringAOP中@annotation與execution的深度示例對比分析
更新時間:2025年08月06日 11:19:39 作者:bemyrunningdog
Spring AOP中@annotation通過注解標記方法,適合定制化橫切邏輯;execution基于方法簽名匹配,用于通用功能增強,兩者互補,根據需求選擇,本文給大家介紹SpringAOP中@annotation與execution的深度示例對比分析,感興趣的朋友一起看看吧
在 Spring AOP 中,@annotation 和 execution 是兩種常用的切點表達式(Pointcut Expression),用于定義哪些方法需要被切面(Aspect)攔截。它們的設計目的、匹配規(guī)則和適用場景有顯著區(qū)別,以下從核心機制、語法、應用場景和示例進行對比分析:
?? ?一、核心概念與機制?
1. ?**@annotation表達式**?
- ?作用?:匹配帶有特定注解的方法。
- ?原理?:基于方法上的注解標記進行攔截,與方法的簽名(類名、方法名等)無關。
- ?適用場景?:
- 需要為特定功能?(如日志、權限校驗)標記方法時。
- 需通過注解傳遞元數據(例如
@Permission(role="admin"))。
- ?優(yōu)點?:靈活性高,與業(yè)務邏輯解耦,適合自定義橫切關注點。
- ?缺點?:需顯式在方法上添加注解,無法批量匹配無注解的方法。
2. ?**execution表達式**?
- ?作用?:通過方法簽名?(返回值、包名、類名、方法名、參數類型)匹配方法。
- ?原理?:基于方法的結構特征攔截,無需方法添加額外注解。
- ?適用場景?:
- 批量攔截特定包/類下的所有方法?(如
com.example.service.*.*(..))。 - 按命名規(guī)范匹配方法(如所有
update*開頭的方法)。
- 批量攔截特定包/類下的所有方法?(如
- ?優(yōu)點?:無需修改代碼,適合通用功能(如接口耗時統(tǒng)計)。
- ?缺點?:表達式復雜,對無規(guī)則的方法難以精確匹配。
?? ?二、語法詳解?
1. ?**@annotation語法**?
@Before("@annotation(com.example.Loggable)")
public void logBefore(JoinPoint joinPoint) {
// 通知邏輯
}- ?參數?:注解的全限定類名(如
com.example.Loggable)。 - ?擴展?:可與自定義注解結合,實現動態(tài)控制(例如
@Loggable(level="DEBUG"))。
2. ?**execution語法**?
@Around("execution(* com.example.service.*.*(..))")
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
// 環(huán)繞通知邏輯
}- ?結構?:
execution(修飾符? 返回值 包.類.?方法名(參數) 異常?)*:通配任意元素(如返回值、單層包名)。..:通配多層包或任意參數(如com..*.ServiceImpl匹配com下所有子包的ServiceImpl類)。
- ?示例?:
- 匹配
UserService的所有方法:execution(* com.service.UserService.*(..)) - 匹配所有
save開頭的方法:execution(* save*(..))
- 匹配
?? ?三、典型場景對比?
| ?維度? | ?**@annotation**? | ?**execution**? |
|---|---|---|
| ?匹配依據? | 方法上的注解標記 | 方法簽名(包、類、方法名、參數等) |
| ?代碼侵入性? | 需在方法上添加注解 | 無侵入,直接匹配方法結構 |
| ?靈活性? | 高(可通過注解參數定制邏輯) | 中(依賴方法命名和包結構) |
| ?適用案例? | - 權限校驗(@RequireAuth)- 日志分級( @LogLevel("DEBUG")) | - 接口耗時統(tǒng)計 - 全局事務管理 - 包級別異常處理 |
| ?復雜匹配能力? | 弱(僅依賴注解是否存在) | 強(支持通配符、邏輯運算符組合) |
?? ?四、代碼示例?
1. ?**@annotation實現自定義日志**?
// 自定義注解
@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è)務方法使用
@Service
public class UserService {
@Loggable
public void createUser() { ... }
}2. ?**execution實現方法耗時統(tǒng)計**?
@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?:
當需要精細控制且邏輯與業(yè)務無關時(如權限、審計日志),通過注解實現解耦。 - ?優(yōu)先
execution?:
需批量攔截?(如全局性能監(jiān)控)或無法修改源碼時,通過方法簽名覆蓋。 - ?混合使用?:
復雜場景可組合表達式,例如:
@Before("@annotation(com.example.Auth) && execution(* com.service.*.*(..))")?? ?總結?
- ?**
@annotation?:注解驅動,精準標記方法,適合高定制化橫切邏輯**。 - ?**
execution?:結構驅動,無侵入匹配,適合通用功能增強**。
兩者本質是互補工具,實際開發(fā)中需根據侵入性容忍度、匹配精度和維護成本綜合選擇。
到此這篇關于SpringAOP中@annotation與execution的深度對比的文章就介紹到這了,更多相關springaop @annotation與execution內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot AOP控制Redis自動緩存和更新的示例
今天小編就為大家分享一篇關于SpringBoot AOP控制Redis自動緩存和更新的示例,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01

