國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
2.4 AspectJ
AspectJ 是由 Java 語言延伸的 AOP 語言。每一個有效的 Java 程式就是一個有效的 AspectJ 程式。AspectJ 的編譯產生出符合 Java byte-code 規範,可執行在 Java virtual machine(JVM)。
在 AspectJ 經由編譯縫合非主功能的實作稱為橫跨(cross-cutting)。AspectJ 定義 了兩種橫跨:靜態橫跨(Static Crosscutting)和動態橫跨(Dynamic Crosscutting)。
動態橫跨是縫合非主要功能至主要功能的執行流程之中。大多數 AspectJ 橫跨都是 動態的。動態橫跨的擴展,甚至取代了核心程序執行流程從而改變系統的行為。
靜態橫跨是修改系統靜態結構(如:類別、介面和剖面)的縫合。其本身不改變系 統的執行行為。靜態橫跨最重要的功能是支援動態橫跨的實作。例如:想要新增成員變 數成員函數至類別或介面中,為了確定特定類別的狀態和行為。這可被使用在動態橫跨 的行為上。另外,靜態橫跨可以被使用在宣告編譯時的警告和錯誤的橫跨多個模組。
以下以案例來說明 如何使用 AspectJ:
AspectJ 範例一:Hello & World
使用 AspectJ Compiler 開發 AspectJ 程式,“Hello” 與“World” 分別由主功能類別 與剖面類別各自輸出。準備主類別 Hello 程式用一般 Java 寫法即可。
圖 2.15 AspectJ 範例一之 Hello
再寫剖面類別 World,寫法有些不同其目的在縫合 Advice。
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
圖 2.16 AOP 範例一之 World
編譯與執行後畫面上出現 ==> Hello World
注意到了嗎,“Hello”與“World”並非在同一字串一起輸出,在主程式中只有印出
“Hello”而已。然而透過剖面縫合程式碼,在此範例上,在呼叫完 main()函式後會接續 執行印出“ World”。
在此簡單的範例可以看出基本的 AspectJ 結構,其組成分成三大部份:原主功能類 別(此例為 Hello)、剖面類別(此例為 World)與非主功能類別。其中非主功類別就是在 剖面類別中與 point-cut 逢合的部份,此例為“System.out”。
以下再看另一個剖面類別的案例,這個案例是接近實際應用案例的一個簡化,如圖 2.17 所示。
圖 2.17 Aspect 類別範例
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
此案例中定義了一個 point-cut 名為“stateChanges” ,它會將映射到主功能類別 程式碼中類別名稱是“Subject”,成員函式名為“click()”的位置。也定義一個 advice,
當跑完 stageChanges 關節後,也就是“Subject.click()”跑完後,對原主功能類別
“Subject”內部屬性進行更新。在 introduction 段落裡,甚至也能為主功能類別添加新 的成員變數與成員函式“observers”和“getObservers()”。
AspectJ 定義的 Joint Points 大概可以涵概了 class 所有的節點,可以分成四類:
object creation、method invocation、field access、error handling。在 Advice 執行時間點可以是 before、after 或 around。在圖表 2.18 明列。
圖 2.18 Join Points in AspectJ
也有人研究用 UML 來表達剖面,設計一套 Aspect-Oriented Design Notation[13], 可在設計階段能視覺化呈現 AspectJ 剖面部份。圖 2-19 是一個範例。
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
圖 2.19 AspectJ Notation 轉換說明
由圖左標準的 UML interaction 圖形轉變到圖右的 AspectJ Design Notation,圖 中是轉變的中繼圖形。由圖左中的«JavaCreate» stereotype 由一個轉化成三個
«create»、«execute»和«initialize»;«JavaCall» stereotype 由一個轉化成二個
«call»和«execute»;«JavaLoad» stereotype 也是由一個轉化成二個 «load» 和
«initialize»。這些 stereotype 都能再有三重 advice,before、after、around。我們 從外部角度來看此設計,可以發現此設計等同擴張了系統的對外接觸面。AspectJ 的擴 張能力已強大到甚至可以改變主功能流程的行為,從而可以使得 Aspect Class 甚至由 輔助變成主要,這個強大若用的好是好,若用不好的話麻煩就大了。