面向切面的程式設計

面向方面程式設計（Aspect-oriented programming，AOP，又譯作面向方面程式設計、面向切面程式設計、剖面導向程式設計），是計算機科學中的一種程式設計範型，旨在將交叉切入關注與作為業務主體的核心關注進行分離，以提高程式程式碼的模組化程度。“方面”（aspect）透過規定叫做 “點切入”（pointcut）的一種量化或查詢，在各種接合點（join point）上應用通告（advice），從而改變現有基礎程式碼的行為（behavior）。比如點切入與通告的一個例項：“對所有方法名以 set * 開頭的方法新增後臺日誌”。該思想使得開發人員能夠將與程式碼核心業務邏輯關係不那麼密切的功能（如日誌功能）新增至程式中，同時又不降低業務程式碼的可讀性。

簡介

面向方面程式設計將程式碼邏輯切分為不同的模組（即關注，一段特定的邏輯功能）。幾乎所有的程式設計思想都涉及程式碼功能的分類，將各項關注（concern）封裝成獨立的抽象模組（如函式、過程、模組、類以及方法等），後者又可供進一步實現、封裝和重寫。部分關注 “交叉切入” 程式程式碼中的數個模組，即在多個模組中都有出現，它們即被稱作交叉切入關注。

日誌功能即是交叉切入關注的一個典型案例，因為日誌功能往往跨越系統中的每個業務模組，即交叉切入（crosscut）所有有日誌需求的類及方法體。而對於一個信用卡應用程式來說，存款、取款、帳單管理是它的核心關注，日誌和持久化將成為交叉切入整個物件結構的交叉切入關注。

方面的概念源於對面向物件程式設計和計算反射的融合。面向方面程式語言擁有很多類似於元物件協議的功能，但有更多的限制。方面相關的程式設計概念包括、混入和。使用面向方面範型的其他方式有和 Hyper/J 的 hyperslices 方式。

歷史

“面向方面程式設計” 這一術語由施樂帕洛阿爾託研究中心的 Chris Maeda 首先提出，但其具體時間已經不可考證了。術語 “交叉切入”（crosscut）是由提出的。同許多重大的技術創新一樣，面向方面程式設計，也是在不同的地方被獨立發展出來。面向方面程式設計的早期工作，主要是由下面幾個機構和人員作出的：

施樂帕洛阿爾託研究中心：Gregor Kiczales、John Lamping、Cristina Videira Lopes 等人，進行的早期工作有關於反射機制和元物件協議，在 1997 年 Gregor Kiczales 發表了論文《面向方面程式設計》；代表系統是基於元物件協議的面向方面程式設計系統和。
國際商用機器公司：William Harrison、Harold Ossher、Peri Tarr 等人，在 1980 年代末進行的早期工作，有關於軟體開發環境與工具整合；後來提出了多維關注分離（MDSOC），代表系統是 Hyper/J。
美國東北大學：Karl Lieberherr 等人，進行的早期工作是研究軟體演化，提出了得墨忒耳定律、傳播模式、適應性程式設計；代表系統是 Demeter/C++ 和 Demeter/Java。
荷蘭特文特大學：Mehmet Aksit 等人，其代表系統是。

基本概念

關注是對軟體工程有意義的小的、可管理的、可描述的軟體組成部分，一項關注通常只同一個特定概念或目標相關聯。傳統的程式語言，以一種線性的文字來描述軟體，只採用一種方式比如類，將軟體分解成模組；這導致某些關注比較好的被捕捉，容易進一步組合、擴充套件；但還有一些關注沒有被捕捉，彌散在整個軟體內部。

關注分離（SOC）是標識、封裝和操縱只與特定概念、目標相關聯的軟體組成部分的能力，即標識、封裝和操縱關注的能力。分離關注使得解決特定領域問題的程式碼從業務邏輯中獨立出來，業務邏輯的程式碼中不再含有針對特定領域問題程式碼的呼叫，業務邏輯同特定領域問題的關係通方面來封裝、維護，這樣原本分散在在整個應用程式中的變動就可以很好的管理起來。

核心關注是一個軟體最主要的關注。在傳統的程式語言中，將軟體分解成模組的主要方式，是支配性分解，即按主關注進行模組分解。用來描述、設計、實現一項給定關注的軟體構造單位是方法。如果兩個關注的實現的方法存在交集，則稱謂這兩個關注相互交叉切入（crosscut）。

面向方面程式設計的核心概念，是從核心關注中分離出交叉切入關注。面向方面程式設計，在支配性分解的基礎上，提供叫做（aspect）的一種輔助的模組化機制，這種新的模組化機制可以捕捉交叉切入關注。

接合點模型

面向方面程式語言的通告相關構件，定義了一個接合點模型（JPM）。一個 JPM 定義了三種東西：

何時通告可以執行。這些叫做，因為在一個執行的程式中，它們是可以有用的接合上額外行為的點。一個接合點想要有用，它必需是可定址的，並且對普通程式設計師是可理解的。它還應該經歷無關緊要的程式變更而保持穩定，使得一個方面經歷這種變更而保持穩定。很多 AOP 實現支援方法執行和欄位引用作為接合點。
規定（或量化）接合點的方式，這叫做。點切入確定是否匹配一個給定接合點。最有用的點切入語言使用像基礎語言的語法（例如使用 Java 簽名），並允許透過命名和組合來重新使用。
指定在接合點要執行的程式碼的手段。稱之為，並且可以在接合點之前、之後和周圍執行。一些實現還支援在一個方面中定義另一個類上的一個方法。

對接合點模型進行比較可以基於：所暴露的接合點，如何規定接合點，在接合點上允許的操作，能夠表達的結構性增強機制。

4.1 AspectJ 的接合點模型

}}

所有有效的 Java 程式也是有效的 AspectJ 程式，但是 AspectJ 容許程式設計者定義叫的特殊構造。方面包含一些對於標準類不能獲得到的實體。它們是擴充套件方法、點切入和通告。

4.1.1 擴充套件方法

允許程式設計者在這個方面之內向現存的類增加方法、欄位或介面。下面例子中，方面 VisitAspect 向類 Point 增加一個 acceptVisitor 方法（參見訪問者模式）：

aspect VisitAspect {void Point.acceptVisitor (Visitor v) {v.visit (this);

}

⋮

}

4.1.2 點切入

在 AspectJ 中接合點包括：方法或構造子呼叫或執行，一個類或物件的初始化，欄位讀或寫訪問，異常處理等。接合點不包括：迴圈、super 呼叫，throw 子句，多個語句等。

點切入是透過組合 “原始點切入指示符”（PCD - primitive pointcut designator）來規定的。例如：

aspect VisitAspect {

⋮

pointcut set : execution ( set ) && this (Point) && within (com.company.);

⋮

}

這個點切入匹配一個方法執行接合點，如果這個方法名字開始於 set，並且此物件（this）是在 com.company 包中型別 Point 的例項。這個點切入可以使用名字 set 來提及。點切入可以複合和命名來重新使用。

“種類” PCD 匹配特定種類的接合點（比如方法執行），並且傾向於接受類似 Java 模樣的簽名作為輸入：

execution ( set(*))

這個點切入匹配一個方法執行接合點，如果這個方法名字開始於 set，並且精確的只有一個任何型別的實際引數。

“動態” PCD 檢查執行時間型別和繫結變數：

this (Point)

這個點切入在當前執行物件是類 Point 的例項之時匹配。注意一個類的未限定名字可以透過 Java 的正常型別查詢來使用。

“範圍” PCD 限制接合點的詞法作用域：

within (com.company.*)

這個點切入匹配在 com.company 包中任何型別的任何接合點。* 是一種形式的萬用字元，它用來匹配具有一個簽名的任何東西。

4.1.3 通告

通告規定在（透過點切入指定的）一個接合點（之前、之後或周圍）執行特定程式碼（指定如若一個方法中的程式碼）。面向方面程式設計的執行時間系統，在這個點切入匹配一個接合點的時候，自動呼叫通告。例如：

aspect VisitAspect {

⋮

after : set {Display.update ;

}

}

這在效果上指定了：“如果 set 點切入匹配這個接合點，在接合點完成之後，執行程式碼 Display.update 。”

實現

下列程式語言已經實現了 AOP，於語言之內或外部庫：

.NET Framework 語言（C# / VB.NET）
PostSharp，是一個商業 AOP 實現，具有免費但有限制的版本。
，提供到在核心程式設計領域包括資料訪問、安全性、日誌、異常處理和其他之中經過實踐檢驗的設施的 API。
ActionScript
Ada
AutoHotkey
C / C++
COBOL
The Cocoa Objective-C 框架
ColdFusion
Common Lisp
Delphi
（IEEE 1647）
Emacs Lisp
Groovy
Haskell
Java
Spring Framework
JavaScript
Lua
make
Matlab
ML
Perl
PHP
Prolog
Python
Racket
Ruby
Squeak Smalltalk
UML 2.0
XML