1.14 About AOP
AOP, 又名Aspect-Oriented Programming, 中文有人說方面(側面)導向, 我這邊的介紹基本上會儘量用原文, 因為我覺得中文翻過來其實不是很直觀. 關於AOP, 個人認為它基本上就是一種interceptor(攔截器)技術, 你可以指定在程式中某些特定的場合要觸發某些特定的行為. 後面會慢慢提到.
試想一下, 今天你想要為你的application中的每個method都去log開始與結束情形. 那你可能就會把這段log的程式重構成一個特定的class (e.g. MyLogger), 儘管如此, 你還是需要在每個你要log的method上呼叫這個class兩次, 這基本上是很OO的作法了, 但聽起來還是不夠好; 透過AOP, 你可以很簡單的指定MyLogger class上的特定方法在application中的每個method被呼叫的時候也一並被執行.
這裡希望你能夠先理解一點, AOP跟OOP之間的關係並非是競爭(compete), 而是AOP補足(complement)了OOP . OOP確實解決了很多我們現實生活中碰到的問題, 但在前一段的例子中, 你可以看到當出現這種跟橫切(crosscutting)邏輯有關的時候, 尤其是scale較大的情況下, OOP就顯得有點無力了, 你可以想想看為所有method都加上前後logging method是多繁瑣且重複的工, 這其實滿不OO的. 當然, 你也不可能用AOP去開發整個application, 畢竟技術的目的不同. 所以在用OOP開發的過程中, 我們可以在碰到crosscutting的情況下借助AOP的特性讓開發更為順暢.
AOP Concepts
AOP的概念是由很多東西組成的, 這邊就一一條列出來:
Joinpoints: 所謂的jointpoint就是在application執行的過程中被良好定義(well-defined)的一個點. 典型的joinpoints如一個對方法的呼叫, 類別的初始化或物件實例化等. Joinpoint是AOP的核心概念且其定義了你可以於application中的何處透過AOP插入額外的邏輯.
Advice: 在特定的joinpoint上執行的程式就是advice. Advice有很多種, 如before, after等. 在OOP的角度來說, advice是以class中的method的形式存在的.
Pointcus: 一個Pointcut就是一組joinpoints的集合(collection), 其用意是用來定義何時要執行某個advice. 通常你可以透過複雜的關係去構成(compose)pointcuts, 進而在advice被執行時去達到約束的效果.
Aspects: 一個aspect就是advice跟pointcuts的組合(combination). 這個組合定義了一段需在application中某處被執行的邏輯.
Weaving: 這就是實際上在合適的時間點於application中插入aspects的流程. 縫合(weaving)的時間點基本上可以分為三種:
Compile time: Static AOP的做法, 通常會被當作是build process的額外步驟
Runtime: Dynamic AOP的做法
Load-time weaving (LTW): AspectJ提供, 這比較複雜, 基本上就是當bytecode被classloader load的時候進行縫合
Target: 當一個物件的execution flow被某些AOP process更改了, 這個物件就稱為target object (a.k.a. advised object).
Introduction: 這是一種可以供你更改一個物件的結構的流程(process), 講白一點就是改變物件行為, 但是卻不用修改該類別的程式碼. 這基本上就是在執行時期動態加入方法或行為的方式.
Types of AOP
AOP基本上只有分為以下兩種, 主要的差別就是weaving的時間點以及weaving的手段
Static AOP: 大多數的AOP都是static的, 對static AOP來說, weaving就是build process的額外步驟. 用Java的角度來看, 透過static AOP達成的weaving基本上都會更改到application的bytecode, 若有必要的話, 也會改變或著是擴張原本的code. 很明顯地, 這是效能比較好的做法, 畢竟最終的結果就是bytecode, 而不必於runtime的時候去決定advice的執行時機.
這種做法的缺點就是不管你對aspect做了多少變更, 儘管只是多加了一個很小的joinpoint, 你都必須要重新compile你的application, 最常見的例子就是AspectJ的compile-time weaving了.
Dynamic AOP: Spring AOP就是屬於這一種, weaving的動作會在runtime的時候動態地執行. 至於細節如何達成, 則要依實作而定. 對Spring來說, 主流的方式就是為所有的advised object創造proxy, 並且允許advice在需要的時候被呼叫.
這種做法的一個小缺點就是效能沒有static AOP那麼好, 但好處是很明顯的, 你不必因為任何一點對aspect的更改就要重新compile你的application.
Proxies in Spring AOP
CGLIB proxy
JDK dynamic proxy
Advice in Spring
Before
After returning
After (finally)
Around
Throws
Introduction
Last updated