來源:blog.csdn.net/duxd185120/article/details/109210224
學習一個模塊的設計主要是看介面設計,通過介面設計我們就能夠從整體知道模塊怎么實作的,具體實作就是組裝這些介面來進行實作的,知道了模塊介面設計,實作也就變得很簡單了,
本文主要從aop背景出發點,來自己去想需要哪些介面,就能夠描述一個模塊的功能設計規則,
AOP產生背景
使用面向物件編程 ( OOP )有一些弊端,當需要為多個不具有繼承關系的物件引人同一個公共行為時,例如日志、安全檢測等,我們只有在每個物件里參考公共行為,這樣程式中就產生了大量的重復代碼,程式就不便于維護了,所以就有了一個對面向物件編程的補充,即面向方面編程 ( AOP ), AOP 所關注的方向是橫向的,區別于 OOP 的縱向,
什么是AOP
什么是面向方面編程,3個程序:
- 找到橫切點:首要目標確定在程式的哪個位置進行橫切邏輯
- 橫切邏輯(業務代碼):橫切邏輯代碼,這個就是橫切業務代碼,與aop無關
- 織入:將橫切邏輯織入到橫切點
開發者主要關心的是橫切邏輯的撰寫,只需要很少的代碼撰寫確定橫切點有哪些,而不需要去為每個橫切點添加橫切邏輯,不然就是面向物件編程了,
既然是橫向的編程,那么在我們的程式中,哪些可以作為橫線切入點呢?
看下示例代碼:
public class Test {
public static void main(String[] args) {
//@1
B b = new B();
//@2
b.method();
//@3
B.say();
}
static class B {
//欄位
//@4
private String name;
//構造方法
public B() {
//@1.1
}
//物件方法
public void method(){
//@2.2
}
//靜態方法
static void say(){
//@3.3
}
}
}
所以我們可以將橫切點主要分為兩大類:欄位、方法,方法又分為很多種,

橫切點有很多地方,從代碼上看得見的,有如下幾個地方:
-
使用建構式創建物件
-
- 建構式執行
-
物件方法呼叫
-
- 物件方法執行
-
靜態方法呼叫
-
- 靜態方法執行
-
反射讀寫物件欄位
目標1:找到橫切點
那么怎么去定義一個橫切點呢?怎么用一個介面來描述一個橫切點呢?
在Java中,一切皆物件,在Java中一個類有2方面內容:欄位、方法(建構式、物件方法、靜態方法),java中使用AccessibleObject來抽象公共行為,方法:就是一段可以執行的程式,一段代碼,
所以在橫切點介面中,首先一個功能就是回傳給用戶當前橫切點,有兩種情況:
- 如果橫切點作用于物件(物件欄位、物件方法、建構式),則不僅需要回傳AccessibleObject,還需要回傳當前物件,因為呼叫通過反射呼叫物件方法需要傳入當前物件,
- 如果橫切點作用于類,則僅回傳AccessibleObject即可,
另一個介面功能就是要不要考慮在橫切點來控制多個橫切邏輯的呼叫,這個可以有框架支持,也可以由橫切點控制,這對應的就是責任鏈模式的API設計,比如tomcat中的Filter鏈式呼叫就是以集合形式呼叫;netty中的Handler組織就是以鏈表形式,如果是以集合形式呼叫,則在橫切點介面需要定義一個方法來鏈式呼叫,(aop聯盟的JoinPoint采用是集合形式呼叫)
那么AOP聯盟使用JointPoint介面來定義橫切點,
public interface Joinpoint {
Object proceed() throws Throwable;
Object getThis();
AccessibleObject getStaticPart();
}
Object proceed() throws Throwable: 鏈式呼叫橫切點
Object getThis(); 回傳連接點當前物件,如果當前連接點是靜態,比如靜態方法,則該方法回傳null,因為反射不需要物件,而且靜態方法是通過類呼叫的,壓根就沒有物件,所以回傳null,spring aop不支持靜態方法的攔截,所以在spring中這里回傳的就是目標物件(被代理物件)
AccessibleObject getStaticPart(); 回傳連接點靜態部分,對于連接點是方法,回傳的就是Method物件,
現在對連接點的設計比較清晰了,然后就是對連接點的擴展了,比如可執行程式(構造方法、Method)的子介面,欄位的子介面(aop聯盟沒有定義,只有方法級別的),
AOP聯盟對連接點介面的設計:

比如在MethodInvocation,就是回傳Method,
目標2:橫切邏輯(增強)抽象定義
增強的抽象,其實就需要連接點資訊,畢竟增強是要投入到一個地方的,所以需要連接點資訊,
在aop聯盟的介面定義:

Advice作為一個tag標識,在aop聯盟中使用攔截器來作為增強的命名,這里完全可以去掉Interceptor,而直接定義一個MethodAdvice,之所以定義為Interceptor,是因為攔截器命名更符合編程命名規范,讓人從命名就知道介面功能,
在MethodInterceptor,傳入連接點資訊(因為是方法攔截,所以這里是方法級別的連接點介面定義)
Object invoke(MethodInvocation invocation) throws Throwable;
目標3:織入
首先就是怎么織入,織入由兩種方案,
- 靜態織入:采用自定義類加載器機制,自定義類加載器根據織入規則在加載class檔案期間對class檔案動手織入橫切邏輯,然后將改動后的class檔案交給JVM運行,
- 動態織入:由多種選擇,動態代理(JDK Proxy)、動態位元組碼生成技術(cglib)
spring采用動態織入,動態織入就是生成代理物件,代理物件中維護了當前連接點所有攔截器,然后呼叫目標方法時被代理類攔截,在代理類中作aop功能,
來一個完整的流程圖:

Spring AOP的實作基于AOP聯盟介面標準設計實作的,全域看下aopalliance有哪些介面以及介面的API設計,我們上面已經分析完了,
AOP聯盟的介面很少:

近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/442765.html
標籤:Java
