在 AspectJ 以「擴展 Java 語法、專用編譯器 (ajc)、載入期織入 (LTW) 需特殊啟動腳本」確立標準地位時,AspectWerkz (AW) 由 Jonas Bonér 與 Alexandre Vasseur 創建,走了一條**純 Java、無語法擴展、部署極簡**的差異化道路。雖後來 AspectWerkz 併入 AspectJ 5 (成為其代理風格織入引擎),但其設計理念 — **「不修改建構流程、不侵入源碼、運行時動態織入」** — 仍具備極高參考價值,尤其適合:**無法控制啟動腳本的受管環境 (共享主機、舊版應用伺服器)、需零依賴引入 AOP 的棕地專案、動態代理無法滿足 (如攔截私有方法、建構子、final 方法) 的場景。**
| 術語 | 定義 | 例子 |
|---|---|---|
| Joinpoint | 程式執行中可定義切入點的位置 | 方法呼叫、方法執行、例外拋出、欄位讀寫、建構子執行 |
| Pointcut | 選擇一組 Joinpoint 的謂語表達式 | execution(* com.service.*.*(..))、@annotation(Transactional) |
| Advice | 在 Pointcut 位置執行的程式碼邏輯 | Before/After/AfterReturning/AfterThrowing/Around |
| Aspect | Pointcut + Advice 的模組化封裝 | LoggingAspect, TransactionAspect, SecurityAspect |
| Weaving | 將 Advice 植入目標類別的過程 | 編譯期 (CTW)、類載入期 (LTW)、運行期 (代理/字節碼重寫) |
| Introduction | 為現有類別動態新增介面/方法/欄位 | 讓任意 POJO 實作 Monitorable 介面 |
java.lang.instrument.ClassFileTransformer,註冊為 JVM Agent。JVM 載入類別前回調 transform(),AW 解析類別字節碼,根據定義織入 Advice,返回修改後字節碼。java -javaagent:aspectwerkz.jar -cp ... MainClass (JDK 5+ 標準 Agent 协议)。AW 提供 aspectwerkz 封裝腳本自動適配 JVM 版本。-javaagent);類載入期增加延遲;生產環境需嚴格測試織入正確性。javac 編譯產生 .class。awc (AspectWerkz Compiler) 讀取編譯輸出目錄 + aop.xml 定義,輸出織入後 .class。
org.aspectwerkz
aspectwerkz
2.2.3
org.codehaus.mojo
aspectwerkz-maven-plugin
2.2.3
compile
com.example.aspect.LoggingAspect
src/main/resources/aop.xml
package com.example.aspect;
import org.aspectwerkz.joinpoint.ProceedingJoinPoint;
public class LoggingAspect {
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
String method = pjp.getSignature().getName();
long start = System.nanoTime();
try {
System.out.println("[AW] Entering: " + method);
return pjp.proceed(); // 執行目標方法
} finally {
long elapsed = System.nanoTime() - start;
System.out.println("[AW] Exiting: " + method + " took " + elapsed/1_000_000 + " ms");
}
}
}
package com.example.service;
public class OrderService {
public void placeOrder(String itemId) {
System.out.println("Placing order for: " + itemId);
// 業務邏輯...
}
}
AW 支援為現有類別動態混入介面實作:
// 建構子切點
// 介面
public interface Monitorable {
long getCreationTime();
void setCreationTime(long t);
}
// Mixin 實作 (需無參構造函式)
public class MonitoringMixin implements Monitorable {
private long creationTime;
public long getCreationTime() { return creationTime; }
public void setCreationTime(long t) { creationTime = t; }
}
// 使用
OrderService svc = new OrderService();
Monitorable m = (Monitorable) svc; // 強制轉型成功!
m.setCreationTime(System.currentTimeMillis());
**威力**:無修改原始碼,賦予任意物件新能力 (監控、序列化、快取、安全標記)。
AspectWerkz 核心織入引擎已併入 AspectJ 5 (2005)。現代專案請直接使用 **AspectJ @AspectJ 風格 + Spring AOP / LTW**:
aspectj-maven-plugin (CTW) 或 -javaagent:aspectjweaver.jar (LTW)。@Aspect, @Pointcut, @Around, @DeclareParents (對應 Introduction)。@EnableAspectJAutoProxy (代理模式) / @EnableLoadTimeWeaving (LTW)。AspectWerkz 以**「輕量、無侵入、雙模式織入、Introduction 黑科技」**證明了 AOP 不必綁定語言擴展。雖專案已併入 AspectJ,但其設計啟示 — **字節碼級別的靈活織入、建構與部署分離、動態能力賦予** — 依然活躍於現代框架 (Spring, Quarkus, Micronaut, ByteBuddy, Arthas) 中。理解 AW,是理解 Java 動態化能力的關鍵一課。