面向切面編程(AOP)讓橫切關注點(日誌、事務、權限、驗證)與業務邏輯解耦。Spring 基於動態代理實現 AOP,註解配置比 XML 更友好重構、錯誤更易排查。本文系統梳理核心概念、啟用方式、切點表達式、參數綁定及五大通知類型。
@Aspect)@Pointcut)@Before 等)@Configuration
@EnableAspectJAutoProxy // 或 XML: <aop:aspectj-autoproxy/>
public class AppConfig {}
只有開啟自動代理,IOC 容器才會為標註 @Aspect 的 Bean 生成代理對象。
execution(* aop.library.BookShop.sell(Book)) 匹配指定方法。常用通配符:
*:返回類型、包名、類名、方法名..:任意參數列表

通過 args(paramName) 將目標方法參數傳給切點方法,再由通知方法接收:
@Pointcut("execution(* aop.library.BookShop.sell(Book)) && args(book)")
public void sell(Book book) {}
@Before("sell(book)")
public void charge(Book book) {
System.out.println("這本書叫:" + book);
}
| 類型 | 註解 | 執行時機 | 典型場景 |
|---|---|---|---|
| 前置通知 | @Before | 目標方法前 | 權限檢查、參數驗證 |
| 後置通知 | @After | 目標方法後(無論正常/異常) | 資源清理、日誌記錄 |
| 返回通知 | @AfterReturning | 正常返回後 | 結果增強、緩存更新 |
| 異常通知 | @AfterThrowing | 拋出異常時 | 異常統一處理、告警 |
| 環繞通知 | @Around | 完全控制目標方法執行 | 事務管理、性能監控、緩存攔截 |
// 1. 基於切點表達式直接配置
@Before("execution(* *..*.*(..))")
public void logAll(JoinPoint jp) { ... }
// 2. 基於已定義切點引用(推薦,復用性強)
@Before("sell(book)")
public void charge(Book book) { ... }
@Around 實現事務等需完整控制流程的場景JoinPoint、目標參數),避免 Object[]@Order 或實現 Ordered 控制多切面執行順序