1. 程式人生 > >Spring AOP學習筆記(一):基礎概念

Spring AOP學習筆記(一):基礎概念

AOP產生背景

AOP(Aspect Oriented Programming),即面向切面程式設計,可以說是OOP(Object Oriented Programming,面向物件程式設計)的補充和完善。OOP引入封裝、繼承、多型等概念來建立一種物件層次結構,用於模擬公共行為的一個集合。不過OOP允許開發者定義縱向的關係,但並不適合定義橫向的關係,例如日誌功能。日誌程式碼往往橫向地散佈在所有物件層次中,而與它對應的物件的核心功能毫無關係對於其他型別的程式碼,如安全性、異常處理和透明的持續性也都是如此,這種散佈在各處的無關的程式碼被稱為橫切(cross cutting),在OOP設計中,它導致了大量程式碼的重複,而不利於各個模組的重用。AOP技術恰恰相反,它利用一種稱為"橫切"的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性。

我們在開發的過程中會對軟體開發進行抽象、分割成各個模組或物件。例如,我們會對API進行抽象成四個模組:Controller,Service,Gateway,Command.這很好地解決了業務級別的開發,但對於系統級別的開發我們很難聚焦。比如、對於每一個模組需要進行打日誌、程式碼監控、異常處理。以打日誌為例,我只能將日誌程式碼巢狀在各個物件上,而無法關注日誌本身,而這種現象又偏離了OOP思想。



為了能夠更好地將系統級別的程式碼抽離出來,去掉與物件的耦合,就產生了面向AOP(面向切面)。如上圖所示,OOP屬於一種橫向擴充套件,AOP是一種縱向擴充套件。AOP依託於OOP,進一步將系統級別的程式碼抽象出來,進行縱向排列,實現低耦合。

AOP應用場景

AOP在系統開發中應用非常廣泛,常見場景如下:

  • 事務處理
  • 日誌處理
  • 異常處理
  • 許可權控制
  • 系統性能監控
  • 其他

AOP的基本概念

AOP核心概念

  1. Join point(連線點):可以被切入的點,但不一定被切入。名詞
  2. Point cut(切點):該切入哪些Join point。形容詞
  3. Advice(通知):切入後做什麼。比如打日誌,許可權管理,等等。動詞
  4. Aspect(切面): Aspect 是Point cut與Advice的組合。在哪些點切入,切入後做什麼

關於Join point和Point cut的區別

可以理解為Point cut為形容詞,而Join point為名詞。被切入的都是符合Point cut描述的Join point。

上面是關於AOP中幾個基本概念的定義,下面看下有關我們使用時的一些概念:

其他概念

  1. Target(目標物件):業務中需要被織入的具體物件。
  2. AOP proxy(AOP代理):Proxy即代理,並不屬於AOP的成員,但卻是整個AOP的具體實施者。在 Spring AOP 中, 一個 AOP 代理是一個 JDK 動態代理物件或 CGLIB 代理物件。
  3. Weaving(織入):就是整個AOP的過程,這個過程就叫做Weaving。

Weaving(織入)有三種方式:

Spring 採用動態代理織入, 而AspectJ採用編譯器織入和類裝載期織入.

  • 編譯器織入, 這要求有特殊的Java編譯器.
  • 類裝載期織入, 這需要有特殊的類裝載器.
  • 動態代理織入, 在執行期為目標類新增增強(Advice)生成子類的方式.

通知型別

  • 前置通知(Before advice):在某連線點之前執行的通知,但這個通知不能阻止連線點之前的執行流程(除非它丟擲一個異常)。
  • 後置通知(After returning advice):在某連線點正常完成後執行的通知:例如,一個方法沒有丟擲任何異常,正常返回。
  • 最終通知(After (finally) advice):當某連線點退出的時候執行的通知(不論是正常返回還是異常退出)。
  • 環繞通知(Around Advice):包圍一個連線點的通知,如方法呼叫。這是最強大的一種通知型別。環繞通知可以在方法呼叫前後完成自定義的行為。它也會選擇是否繼續執行連線點或直接返回它自己的返回值或丟擲異常來結束執行。
  • 異常通知(After throwing advice):在方法丟擲異常退出時執行的通知。

AOP原理

上面說到了AOP可以在編譯時候將程式碼織入到指定的方法或者屬性上,或者在執行的時候動態的將程式碼切入到指定的方法或者屬性中,這描述了AOP應該要做的事情,其實也基本算是它的原理了,AOP實現的關鍵就是建立AOP代理,代理有靜態代理和動態代理之分,其中AspectJ為靜態代理,Spring AOP是動態代理,這裡把靜態和執行時動態的分開說。

  • AspectJ(靜態代理)
  • Spring AOP(動態代理)

AspectJ編譯時增強(靜態代理)

AspectJ編譯時增強,既是靜態代理增強,也就是會在編譯階段生成代理,將程式碼織入到Java的位元組碼中去。

Spring AOP的執行時增強(動態代理)

Spring AOP是基於代理機制的,並且Spring AOP使用的是動態代理增強,動態代理不會改變類的位元組碼,而是動態的生成代理物件。Spring AOP的動態代理機制有兩種方式:JDK動態代理和CGLIB動態代理。

Spring有兩種實現AOP的方式

  1. Java動態代理
  2. CGlib。預設使用動態代理

當目標物件沒有實現介面時,就會使用後者。

JDK動態代理

JDK動態代理需要被代理的類必須實現一個介面,通過使用反射來接受被代理的類。

CGLIB動態代理

CGLIB動態代理可以不用需要被代理類必須實現介面,被代理類可以是一個類。

 

參考:

https://www.cnblogs.com/hongwz/p/5764917.html