承接第一部分,本文將元資料視為「多維關注點空間中的簽名」,提出一套系統化的註解設計與使用準則,並探討元資料對 AOP 採用曲線的影響。核心觀點:註解不應僅為切面服務,而應描述程式元素在多個關注點維度上的語義投影,從而實現類別與切面的鬆耦合。
傳統方法簽名(名稱、參數、回傳型別)只能反映單一核心業務語義(如 credit(float)),無法表達交易、授權、日誌等橫切關注點。強行在名稱編碼橫切資訊(transactional_authorized_credit)會導致簽名糾結:名稱變更波及所有呼叫端,業務呼叫端被迫承擔無關關注點負擔。
Java 5 註解提供了解法:
@Transactional(Required)
@Authorized("accountModification")
public void credit(float amount);
概念上,每個註解代表一個維度的投影:
creditRequiredaccountModification
這構成了多維介面:每個關注點的實作只消費相關維度的投影,業務邏輯完全不知曉交易/授權註解的存在,保持無知性。
public class Account {
@Transactional(kind=Required)
@WriteOperation
@Authorization(kind="bankModification")
public void credit(float amount) { ... }
@Transactional(kind=Required)
@WriteOperation
@Authorization(kind="bankModification")
public void debit(float amount) { ... }
@Transactional(kind=None)
@ReadOperation
@Authorization(kind="bankQuery")
public float getBalance() { ... }
}
業務呼叫端(AccountServices.transfer())只見業務維度;交易管理切面只匹配 @Transactional 投影;授權切面只匹配 @Authorization。各維度正交、獨立演進。
within(com.myapp..*)),而非逐一定點註解。execution(* *.get*()) 捕獲所有 getter,優於 @Getter。避免單一切面覆蓋全系統導致切點脆弱複雜。建立抽象基底切面(含通知邏與抽象切點),每個子系統(套件、類別)提供具體子切面實作抽象切點。這是 Participant 模式 核心,適用於交易、執行緒安全、安全性等橫切功能。
@TransactionAttribute、@RolesAllowed)錯誤:@ReadLock、@WriteLock(綁定鎖實作)
正確:@ReadOperation、@WriteOperation(描述語義狀態變更)
抽象註解允許同一組標註服務多種橫切實作:
// 基底切面
public abstract aspect ReadWriteLockSynchronizationAspect
perthis(readOperations() || writeOperations()) {
public abstract pointcut readOperations();
public abstract pointcut writeOperations();
// 通知實作鎖邏輯...
}
// 具體子切面:銀行系統
public aspect BankingReadWriteLockSynchronizationAspect
extends ReadWriteLockSynchronizationAspect {
pointcut lockManagedExecution()
: execution(* banking.Customer.*(..)) || execution(* banking.Account.*(..));
public pointcut readOperations()
: execution(@ReadOperation * *.*(..)) && lockManagedExecution();
public pointcut writeOperations()
: execution(@WriteOperation * *.*(..)) && lockManagedExecution();
}
當大量方法需相同註解組合時,改以切面以橫切方式批量宣告:
// Customer 類別內嵌註解者切面
private static aspect Annotator {
declare annotation: public Customer.*(..): @Transactional;
}
進階:建立橋接切面將業務註解轉換為橫切註解:
public aspect BusinessTransactionBridge {
declare annotation: @Purchase *.*(..): @Transactional;
declare annotation: @OrderProcessing *.*(..): @Transactional;
}
類別僅標註業務語義(@Purchase),橋接切面負責映射至技術切面所需註解,進一步解耦。
註解若為「切面驅動參數」(唯有為了被切面捕獲而存在),類別對切面產生依賴,違反無知性。若註解描述類別固有語義屬性(如「此操作修改狀態」、「此操作需授權」),類別對切面保持無知。遵循準則 4(抽象註解)即自然滿足無知性。
註解為 AOP 新手提供「訓練輪」:先以標記式切點快速見效,隨經驗累積重構為抽象註解與 Participant 模式。這平滑了從 OOP 到 AOP 的篩選曲線,並非妥協,而是演進階梯。
元資料與 AOP 確為天作之合。標準化元資料移除了 AOP 邁入主流的最後障礙。關鍵在於:將註解視為多維介面的投影,設計語義導向的抽象註解型別,優先挖掘隱式簽名模式,善用切面繼承與橋接機制。雙方若能尊重彼此邊界、發揮所長,必能共譜軟體模組化新篇章。