面試官:說說SpringAOP實現(xiàn)原理?
AOP(Aspect-Oriented Programming,面向切面編程)是一種編程技術,它允許開發(fā)者在不改變現(xiàn)有代碼的情況下,增加新的功能或行為,這些功能或行為被稱為“切面”。
AOP 可以通過預編譯方式和運行期動態(tài)代理的方式來實現(xiàn),它的主要目的是降低業(yè)務邏輯的耦合性,提高程序的可重用性和開發(fā)效率。
AOP 常用于統(tǒng)一功能的處理,例如:事務管理、日志記錄、權(quán)限檢查等功能。
1.AOP優(yōu)點分析
使用 AOP 的主要原因有以下幾點:
- 模塊化:通過將公共行為(如日志記錄、事務管理)提取為獨立的切面,可以使代碼更加模塊化,提高代碼的可維護性和可讀性。
- 減少重復代碼:通過使用 AOP,可以將重復的代碼(如日志記錄、權(quán)限檢查)提取到一個切面中,避免在多個地方重復編寫相同的代碼。
- 解耦:AOP 允許開發(fā)者將業(yè)務邏輯與橫切關注點(如日志記錄、事務管理)分離,從而降低業(yè)務邏輯的耦合性,提高程序的可重用性和可擴展性。
2.AOP技術實現(xiàn)
A擴展性實現(xiàn)技術主要分為兩大類:靜態(tài)代理和動態(tài)代理。
- 靜態(tài)代理:通過 AOP 框架提供的命令進行編譯,從而在編譯階段生成 AOP 代理類。這種方式也被稱為編譯時增強。靜態(tài)代理包括編譯時編織和類加載時編織兩種方式。
- 動態(tài)代理:在運行時在內(nèi)存中“臨時”生成 AOP 動態(tài)代理類,因此也被稱為運行時增強。動態(tài)代理主要有兩種實現(xiàn)方式:
- JDK 動態(tài)代理:JDK 動態(tài)代理要求被代理的類必須實現(xiàn)一個接口,它通過反射來接收被代理的類,并使用 InvocationHandler 接口和 Proxy 類實現(xiàn)代理。
- CGLIB 動態(tài)代理:CGLIB 則是一個代碼生成的類庫,它可以在運行時動態(tài)地生成某個類的子類,通過繼承的方式實現(xiàn)代理。如果目標類沒有實現(xiàn)接口,Spring AOP 會選擇使用 CGLIB 來動態(tài)代理目標類。
3.AOP實現(xiàn)原理
Spring AOP(面向切面編程)的實現(xiàn)原理主要基于動態(tài)代理技術,它提供了對業(yè)務邏輯各個方面的關注點分離和模塊化,使得非功能性需求(如日志記錄、事務管理、安全檢查等)可以集中管理和維護,而不是分散在各個業(yè)務模塊中。
Spring AOP 實現(xiàn)原理的關鍵要點如下:
- 代理機制:
JDK 動態(tài)代理:對于實現(xiàn)了接口的目標類,Spring AOP 默認使用 JDK 的 java.lang.reflect.Proxy 類來創(chuàng)建代理對象。代理對象會在運行時實現(xiàn)代理接口,并覆蓋其中的方法,在方法調(diào)用前后執(zhí)行切面邏輯(即通知,advice)。
CGLIB 動態(tài)代理:對于未實現(xiàn)接口的類,Spring AOP 會選擇使用 CGLIB 庫來生成代理對象。CGLIB 通過字節(jié)碼技術創(chuàng)建目標類的子類,在子類中重寫目標方法并在方法調(diào)用前后插入切面邏輯。
- 關鍵概念:
切面(Aspect):切面是一個包含了橫切關注點聲明的模塊化單元,它可以有多個切入點和通知組成。
切入點(Pointcut):切入點定義了匹配通知應該被織入的方法或方法執(zhí)行點的規(guī)則表達式。
通知(Advice):通知是在特定切入點處執(zhí)行的代碼片段,分為多種類型,如前置通知(Before advice)、后置通知(After returning advice)、異常后通知(After throwing advice)、最終通知(After (finally) advice)以及環(huán)繞通知(Around advice)。
織入(Weaving):織入是指將切面應用到目標對象來創(chuàng)建一個新的代理對象的過程。在 Spring AOP 中,織入發(fā)生在運行時,通過代理對象的方式實現(xiàn)。
代理工廠:Spring 內(nèi)部通過 ProxyFactory 或相關的 AOP 基礎設施(如 Advisor、AdvisorChainFactory 等)來創(chuàng)建和管理代理對象。
執(zhí)行流程:當客戶端通過代理對象調(diào)用目標方法時,代理對象會攔截這個調(diào)用,根據(jù)切面配置找到對應的通知,并按照通知類型的不同執(zhí)行相應的增強邏輯。例如,如果是環(huán)繞通知,它會完全控制原始方法的調(diào)用過程,可以在調(diào)用前后插入自定義邏輯,甚至決定是否執(zhí)行原方法。
通過上述方式,Spring AOP 巧妙地實現(xiàn)了對目標對象方法的攔截和增強,從而實現(xiàn)了面向切面編程的功能。