1. 程式人生 > >Spring之思維導圖(AOP篇)

Spring之思維導圖(AOP篇)

原文轉載:https://mp.weixin.qq.com/s/6WK2oV-vaqPGQpIIR5UeHA

什麼是aop

AOP(Aspect-OrientedProgramming,面向方面程式設計),可以說是OOP(Object-Oriented Programing,面向物件程式設計)的補充和完善。OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌程式碼往往水平地散佈在所有物件層次中,而與它所散佈到的物件的核心功能毫無關係。這種散佈在各處的無關的程式碼被稱為橫切(cross-cutting)程式碼,在OOP設計中,它導致了大量程式碼的重複,而不利於各個模組的重用。

aop作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開。

而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。

aop使用場景

aop框架種類

  • AspectJ

  • JBoss AOP

  • Spring AOP

使用aop可以做的事情有很多。

  • 效能監控,在方法呼叫前後記錄呼叫時間,方法執行太長或超時報警。

  • 快取代理,快取某方法的返回值,下次執行該方法時,直接從快取裡獲取。

  • 軟體破解,使用AOP修改軟體的驗證類的判斷邏輯。

  • 記錄日誌,在方法執行前後記錄系統日誌。

  • 工作流系統,工作流系統需要將業務程式碼和流程引擎程式碼混合在一起執行,那麼我們可以使用AOP將其分離,並動態掛接業務。

  • 許可權驗證,方法執行前驗證是否有許可權執行當前方法,沒有則丟擲沒有許可權執行異常,由業務程式碼捕捉。

觀察一下傳統編碼方式與使用aop的區別

核心概念

描述AOP常用的一些術語有通知(Adivce)、切點(Pointcut)、連線點(Join point)、切面(Aspect)、引入(Introduction)、織入(Weaving)、通知(Advice)等。

環繞通知(@Around):包圍一個連線點(join point)的通知,如方法呼叫。這是最強大的一種通知型別,環繞通知可以在方法呼叫前後完成自定義的行為,它也會選擇是否繼續執行連線點或直接返回它們自己的返回值或丟擲異常來結束執行。

簡單例子

相比xml配置,基於註解的方式更加簡潔方便。

@Aspectpublic class TransactionDemo {
    
    @Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")    public void point(){
        
    }
    
    @Before(value="point()")    public void before(){
        System.out.println("transaction begin");
    }
    
    @AfterReturning(value = "point()")    public void after(){
        System.out.println("transaction commit");
    }
    
    @Around("point()")    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("transaction begin");
        joinPoint.proceed();
        System.out.println("transaction commit");
    }
}

在applicationContext.xml中配置。

<aop:aspectj-autoproxy />
<bean id = "transactionDemo" class = "com.yangxin.core.transaction.TransactionDemo" />

通過前面介紹可以知道:AOP 代理其實是由 AOP 框架動態生成的一個物件,該物件可作為目標物件使用。AOP 代理包含了目標物件的全部方法,但 AOP 代理中的方法與目標物件的方法存在差異:AOP 方法在特定切入點添加了增強處理,並回調了目標物件的方法。

         代理的方法與目標物件的方法(圖)

Spring 的 AOP 代理由 Spring 的 IoC 容器負責生成、管理,其依賴關係也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 例項作為目標,這種關係可由 IoC 容器的依賴注入提供。

aop開發時,其中需要程式設計師參與的只有 3 個部分:

  • 定義普通業務元件。

  • 定義切入點,一個切入點可能橫切多個業務元件。

  • 定義增強處理,增強處理就是在 AOP 框架為普通業務元件織入的處理動作。

 

為了理清關係,先來個類關係圖。Spring中主要的AOP元件

兩種動態代理方式

Spring預設採取的動態代理機制實現AOP,當動態代理不可用時(代理類無介面)會使用CGlib機制。

Spring提供了兩種方式來生成代理物件: JDKProxy和Cglib,具體使用哪種方式生成由AopProxyFactory根據AdvisedSupport物件的配置來決定。預設的策略是如果目標類是介面,則使用JDK動態代理技術,否則使用Cglib來生成代理。

JDK動態代理

  • JDK動態代理主要涉及到java.lang.reflect包中的兩個類:Proxy和InvocationHandler。InvocationHandler是一個介面,通過實現該介面定義橫切邏輯,並通過反射機制呼叫目標類的程式碼,動態將橫切邏輯和業務邏輯編制在一起。

  • Proxy利用InvocationHandler動態建立一個符合某一介面的例項,生成目標類的代理物件。

CGLib動態代理

  • CGLib全稱為Code Generation Library,是一個強大的高效能,高質量的程式碼生成類庫,可以在執行期擴充套件Java類與實現Java介面,CGLib封裝了asm,可以再執行期動態生成新的class。和JDK動態代理相比較:JDK建立代理有一個限制,就是隻能為介面建立代理例項,而對於沒有通過介面定義業務方法的類,則可以通過CGLib建立動態代理。

知識拓展

通過上面的分析,大家是否有種熟悉的感覺,似乎和攔截器、過濾器的功能相似。那麼問題來了,aop與攔截器、過濾器是什麼關係。

先來回顧一下攔截器與過濾器。如下圖一網友的測試,在web.xml中註冊了TestFilter1和TestFilter2。然後在spring的配置檔案中配置了BaseInterceptor和TestInterceptor。得到的結果如下圖所示。從圖中可以看出,攔截器和過濾器都橫切了業務方法,看似符合aop的思想。

Filter過濾器:攔截web訪問url地址。
Interceptor攔截器:攔截以 .action結尾的url,攔截Action的訪問。
Spring AOP攔截器:只能攔截Spring管理Bean的訪問(業務層Service)

Filter也是AOP的一種實現。