1、介紹
AOP(面向切面程式設計)對OOP(物件導向程式設計)是一種補充,它提供了另一種程式結構的思路。OOP的模組單元是class,而AOP的模組單元是aspect。Spring中一個關鍵的元件是AOP框架,然而,Spring IoC容器並不依賴於AOP,也就是說如果你不想用AOP的話可以不用。
在Spring框架中AOP用來做什麼呢?
- 提供宣告式的企業服務,特別是代替EJB的宣告式服務。最重要的的服務是宣告式事務管理。
- 允許使用者實現自定義的aspect
1.1、AOP概念
- Aspect(方面):橫切多個class的一個關注點的模組化。事務管理是一個很好的例子。在Spring AOP中,aspect可以用普通類或者帶有@Aspect註解的普通類來實現。
- Join point(連線點):程式執行期間的一個點,比如方法的執行或者異常的處理。在Spring AOP中,一個連線點總是代表一個方法執行。
- Advice(通知):一個aspect在一個特定的連線點所採取的動作。通知的型別包括"around"、"before"、"after"。許多AOP框架,包括Spring也是,它們把一個通知作為一個攔截器,維護一個攔截器鏈環繞在連線點上。
- Pointcut(切入點):匹配連線點的一個謂詞。Advice關聯一個切點表示式。Spring預設用AspectJ切點表示式。
- Target object(目標物件):被一個或多個aspect通知的物件。在Spring AOP中是用執行時代理來實現的,因此這個物件總是一個代理物件。
- AOP proxy(AOP代理):為了實現aspect而被AOP框架所建立的一個物件。在Spring框架中,一個AOP proxy可能是一個JDK動態代理或者一個CGLIB代理。
1.2、通知的型別
- Before advice(前置通知):在一個連線點之前執行的通知,但是沒有能力阻止後面的執行(除非它拋異常)
- After returning advice(返回通知):在一個連線點正常執行完以後執行的通知:例如,在一個不拋異常的方法返回時執行
- After throwing advice(異常通知):如果方法因為丟擲異常而退出了才會執行的通知
- After (finally) advice(後置通知):無論連線點正常退出還是異常退出都會執行
- Around advice(環繞通知):環繞一個連線點比如方法呼叫的通知。這是最強的一種通知。環繞通知可以在方法呼叫之前或之後執行自定義的行為。它也負責選擇是否處理連線點方法執行,通過返回一個它自己的返回或者丟擲異常。環繞通知是用得最普遍的一種通知。
1.3、Spring AOP的能力和目標
Spring AOP用純Java實現。目前只支援方法執行的連線點,欄位攔截沒有實現。
1.4、AOP Proxies
Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces.
CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes; business classes normally will implement one or more business interfaces.
預設JDK動態代理,如果物件沒有實現介面則用CGLIB
2、@AspectJ支援
@AspectJ是用註解來標註常規的Java類的一種宣告aspect的風格。
2.1、啟用@AspectJ支援
你需要開啟Spring對於基於@AspectJ aspects的Spring AOP配置的支援,和autoproxying beans的支援。autoproxying的意思是如果Spring檢測到一個bean被一個或多個aspect通知,它將自動為這個bean生產代理以攔截方法呼叫並確保通知被執行。
可以用XML或者Java配置的方式來開啟對@AspectJ的支援。你需要確保在你的工程的classpath下有aspectweaver.jar。
2.2、宣告一個aspect
2.3、宣告一個pointcut
A pointcut declaration has two parts: a signature comprising a name and any parameters, and a pointcut expression that determines exactly which method executions we are interested in. In the @AspectJ annotation-style of AOP, a pointcut signature is provided by a regular method definition, and the pointcut expression is indicated using the @Pointcut annotation (the method serving as the pointcut signature must have a void return type).
宣告一個pointcut有兩部分:一個簽名和一個切點表示式。簽名由一個name和任意引數組成,切點表示式決定對哪些方法執行感興趣。在註解風格的AOP中,一個pointcut簽名就是一個常規方法定義,而pointcut表示式用@Pointcut註解來標識(作為pointcut簽名的方法的返回值必須是void)
Spring AOP還支援下面這樣的切點表示式:
切點表示式可以組合使用
The format of an execution expression is:
2.4、宣告advice
3、基於XML格式的AOP支援
the keywords 'and', 'or' and 'not' can be used in place of '&&', '||' and '!' respectively
4、選擇哪種AOP宣告方式
4.1、Spring AOP or full AspectJ?
4.2、@AspectJ or XML for Spring AOP?
如果你選擇用Spring AOP,那麼你可以選擇用@AspectJ或者XML風格。推薦用@AspectJ。
5、代理機制
Spring AOP用JDK動態代理或者CGLIB來建立目標物件的代理。(首選JDK動態代理)
如果被代理的目標物件至少實現了一個介面,那麼JDK動態代理將會被使用。而且,目標物件實現的所有介面都將被代理。
如果目標物件沒有實現任何介面,那麼一個CGLIB代理將會被建立。
如果你想強制使用CGLIB代理也是可以的,但是你需要考慮一個問題,那就是final方法不能被通知,因為它們不能被覆蓋。
如果你想強制使用CGLIB代理可以這樣做,二者選其一即可:
5.1、理解AOP代理
Spring AOP is proxy-based.(Spring AOP是基於代理的)
理解這個語義是極其重要的。
參考
《Spring Framework Reference Documentation》 4.3.14.RELEASE
Spring文件下載地址
http://repo.springsource.org/libs-release-local/org/springframework/spring/