AOP 即 Aspect-oriented Programming,Aspect 切面,什麼是切面,就是一條大路上的收費站,檢查站,首先它是一個統一的功能單元,或是收費、或是檢查,其次它可以決定對誰收費,對誰收多少費,對誰檢查。與之相對的是 OOP 即 Object-oriented Programming,Object 物件,物件就是大路上的一輛輛汽車,每輛汽車都有一套完成的功能系統,有發動機、車架、車輪、方向盤等,每輛車又各自不同,或是小轎、或是SUV、又或是貨車等等,AOP 是對 OOP 的補充,是程式結構涉及的一種方式。
Aspect:模組化的關注點(切面),例如事務。通常以 @Aspect 註解類形式應用。一個小容器。
package com.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect public class NotVeryUsefulAspect { }
Join point::程式執行過程中的一個點,例如一個方法,或者一個例外處理。Spring AOP 中,通常代表一個方法的執行。在何處執行。
@Before("execution(* com.xyz.dao.*.*(..))") public void doAccessCheck(JoinPoint jp) { // ... }
可以通過 JointPoint 獲取執行點的一系列資料:
getArgs():
方法引數。
getThis()
:返回代理物件。
getTarget()
:返回被代理的物件。
getSignature():
方法描述。
Advice:在 joint point 處需要執行的操作。包括 "around"、"before" 及 "after" 等。advice 通常會被模組化為攔截器,多個 advices 以攔截器鏈的形式作用於 joint point。執行什麼。
@After("execution(* com.xyz.dao.*.*(..))") public void doAccessCheck() { // ... }
關於 advice 順序:
spring aop 中定義順序:@Around、@Before、@After、@AfterReturning、@AfterThrowing
應用 AspectJ 則遵從 @After 作為最終執行順序,於 @AfterReturning、@AfterThrowing 之後執行。
同一個 joint point 處的同類 advice 以 @Order 執行執行順序。
Pointcut:用以匹配 joint point 的斷言,可以稱之為代表一系列 joint point。結合 Advice 使用。匹配何處執行語意。
@Pointcut("execution(public * *(..))") public void publicMethod() {}
Target object:advices 執行的目標物件。代理物件。
AOP proxy:代理,用以實現切面合約。JDK動態代理或者CGLIB 代理。
Weaving:織入,將切面和其它應用物件連結在一起來建立執行物件。組裝。
Spring AOP 目前只支援方法級別的 joint point(spring bean 中的方法),如果需要其它粒度,如屬性欄位,可以使用 AspectJ。
Spring AOP 沒有實現完整的 AOP 功能,它的出現旨在整合 AOP 功能和 Spring IoC 容器,用以解決企業實際應用中常見的問題。
Spring AOP 和 AspectJ 並非競爭關係,它們各自都是非常成熟的框架,適用於不同的目的。Spring 可以在基於 Spring 框架的應用架構中無縫整合 Spring AOP、IoC 及 AspectJ,以完整地使用 AOP 功能。
Spring AOP 是基於代理的,預設使用 JDK 動態代理,用以實現介面代理。
非介面代理需要使用 CGLIB。
ApplicationContext:入口。
AspectJAutoProxyBeanDefinitionParser:AspectJ 解析器,自動發現註冊 AspectJ 風格的切面。
AnnotationAwareAspectJAutoProxyCreator 會根據定義的切點來自動代理相匹配的 bean。AnnotationAwareAspectJAutoProxyCreator 的層次結構如下:
AnnotationAwareAspectJAutoProxyCreator 實現了 BeanPostProcessor 介面,會在對應 Bean 範例化後應用此 BeanPostProcessor。
AnnotationAwareAspectJAutoProxyCreator 用於處理所有 AspectJ 宣告的切面。
基於 AspectJ 的代理工廠。可以用於程式設計方式建立包含切面的物件代理。
//建立代理工廠 AspectJProxyFactory factory = new AspectJProxyFactory(targetObject); // 新增 AspectJ aspect,可以多次新增,可以使 class 或者 instance。 factory.addAspect(SecurityManager.class); //.addAspect(usageTracker); // 獲取物件代理 MyInterfaceType proxy = factory.getProxy();