springAop原理

miller.zc發表於2020-12-18

一、什麼是AOP

AOP是對OOP(物件導向)的補充,OOP是自上而下的將程式抽象成各個層次的物件
而AOP是定義好切入點,只要被這些切入點包含的,都要執行AOP的通知。
(就是多個物件的方法執行前後會觸發相同的一些邏輯,可以將這些邏輯提取出來)。

二、為什麼需要 AOP

相同的邏輯也可以抽取成公共方法,然後要呼叫的時候在各個不同的類裡面呼叫。
但是萬一以後又要加一些其它的公共方法,那就要每個類裡面都去加。
像這種統一邏輯的處理,完全可以用AOP解決,利用aop在這些方法執行前後加一些公共的邏輯
即可,實際上就是動態代理模式。

三、AOP 實現分類

AOP 要達到的效果是,保證開發者不修改原始碼的前提下,去為系統中的業務元件新增某種通用功能(動態代理模式)。

靜態 AOP 實現, AOP 框架在編譯階段對程式原始碼進行修改,
生成了靜態的 AOP 代理類(生成的 *.class 檔案已經被改掉了,需要使用特定的編譯器),比如 AspectJ。

動態 AOP 實現, AOP 框架在執行階段對動態生成代理物件
(在記憶體中以 JDK 動態代理,或 CGlib 動態地生成 AOP 代理類),如 SpringAOP。

四、AOP術語和流程

1、通知(Advice):

就是代理方法,為目標方法(連線點)在執行前後新增一些特殊邏輯

通知分為前置、後置、異常、最終、環繞通知五類。


前置通知(Before):在目標方法被呼叫之前呼叫通知功能
後置通知(After):在目標方法完成之後呼叫通知,此時不會關心方法的輸出是什麼
環繞通知(Around):通知包裹了被通知的方法,在被通知的方法呼叫之前和之後執行自定義的行為。
返回通知(After-returning):在目標方法成功執行之後呼叫通知
異常通知(After-throwing):在目標方法丟擲異常後呼叫通知

2、連線點(Join point)

被攔截到的點,因為Spring只支援方法型別的連線點,實際上就是目標方法

3、切點(Pointcut)

切點就是指定那些地方要被攔截到,定義了“何處”執行通知(代理方法)

4、切面(Aspect)

相當於一個攔截器配置類,定義一個切面,這個切面裡面去定義通知、切點等。

5、織入(Weaving)

在織入切面時,AOP容器會為目標物件動態的建立一個代理物件,也就是動態代理。

6、流程說明:

@Aspect
@Order(-1)  // 該切面應當先於 @Transactional 執行
@Component
public class DynamicDataSourceAspect {


    /**
     * 前置通知,進入切點之前,先切換資料來源。
     * @param point
     * @param targetDs
     */
    @Before("@annotation(targetDs)")
    public void switchDataSource(JoinPoint point, TargetDs targetDs) {
        //判斷,如果沒有此資料來源
        if (!DynamicDataSourceContextHolder.containDataSourceKey(targetDs.value())){
            System.out.println("沒有找到key為[{}]的資料來源,所以當前還是使用預設資料來源!"+targetDs.value());
        }else {
            DynamicDataSourceContextHolder.setDataSourceKey(targetDs.value());
            System.out.println("方法"+point.getSignature().getName()+"上發現@TargetDs註解,"+"當前資料來源已經切換為[{}]!"+targetDs.value());
        }
    }
}


<1>、定義一個切面,也就是一個配置類用@Aspect標註。

<2>、定義通知,也就是代理方法,指定好切點,也就是在遇到什麼方法之後才執行代理方法。

@Before("@annotation(targetDs)"):

定義通知,型別為前置通知@Before,定義切點為帶有targetDs註解的方法,
這裡也可以用方法名掃描的方式來定義切點。



<3>、JoinPoint point就是連線點,被攔截到的點,也就是目標方法

<4>、當執行到對應切點的時候,就會自動執行對應的通知裡面的邏輯。

五、Spring對AOP的支援

AOP代理由spring容器生成和管理,所以在AOP切面中,可以隨意使用和注入其它的springBean。

spring預設使用JDK動態代理來實現AOP代理,這樣就可以為任何實現了介面的物件生成代理物件。
當要代理的物件沒有實現任何介面的時候,spring會自動切換到Cglib的方式生成代理物件

AOP程式設計其實是很簡單的事情,縱觀AOP程式設計,程式設計師只需要參與三個部分:


1、定義普通業務元件(目標物件)

2、定義切入點,一個切入點可能橫切多個業務元件(多個目標物件)

3、定義通知(代理方法),在AOP框架為普通業務元件(目標物件)生成代理物件,執行目標物件方法的時候就自動執行通知(代理方法)的邏輯。

相關文章