目錄
實現步驟:
1 導入AOP依賴
2 編寫切面Aspect
3 編寫通知方法
4 指定切入點表達式
5 測試AOP動態織入
圖示:
一 實現步驟:
1 導入AOP依賴
<!-- Spring Boot AOP依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
2 編寫切面Aspect
@Aspect // 標記為切面類
@Component // 由Spring容器管理
public class LogAspect {// 切入點表達式和通知方法在此定義
}
3 編寫通知方法
通知方法(Advice)?是面向切面編程(AOP)中的核心概念,表示在目標方法(或切入點)的某個執行階段插入的增強邏輯。通俗來說,就是“在某個地方(切入點)做某件事(增強邏輯)”。
通知方法的類型
Spring AOP 提供了5種通知類型,對應不同的執行時機:
注解 | 執行時機 | 典型場景 |
---|---|---|
@Before | 目標方法執行前 | 參數校驗、權限驗證 |
@After | 目標方法執行后(無論是否拋出異常) | 資源清理、日志記錄 |
@AfterReturning | 目標方法正常返回后(無異常時執行) | 記錄結果、緩存數據 |
@AfterThrowing | 目標方法拋出異常后 | 異常處理、告警通知 |
@Around | 包圍目標方法(可自定義方法執行前后邏輯,甚至阻止方法執行) | 性能監控、事務管理 |
代碼實現:
package org.example.spring02.aspect;import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect
public class LogAspect {public void logStart() {System.out.println("【切面-日志】開始");}public void logEnd() {System.out.println("【切面-日志】結束");}public void logReturn() {System.out.println("【切面-日志】返回");}public void logException() {System.out.println("【切面-日志】異常:");}}
4 指定切入點表達式
作用:通過表達式定義哪些方法需要被攔截。
語法結構:
execution([訪問權限] 返回類型 包名.類名.方法名(參數類型) [異常類型])
代碼實現:
精確指定接口的路徑:
@Before("execution(int org.example.spring02.MathMethod.MathCalculator.*(..))")public void logStart() {System.out.println("【切面-日志】開始");}
package org.example.spring02.aspect;import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect
public class LogAspect {@Before("execution(int *(int,int))")public void logStart() {System.out.println("【切面-日志】開始");}@After("execution(int *(int,int))")public void logEnd() {System.out.println("【切面-日志】結束");}@AfterReturning("execution(int *(int,int))")public void logReturn() {System.out.println("【切面-日志】返回");}@AfterThrowing("execution(int *(int,int))")public void logException() {System.out.println("【切面-日志】異常:");}}
5 測試AOP動態織入
package org.example.spring02;import org.example.spring02.MathMethod.MathCalculator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class AopTest {@AutowiredMathCalculator mc;@Testpublic void test01() {int add = mc.add(1, 2);System.out.println(add);}}
二 說說你對AOP的理解?
AOP全稱叫做?Aspect Oriented Programming(面向切面編程)。它是為解耦而生的,解耦是程序員編碼開發過程中一直追求的境界。AOP在業務類的隔離上,做到了解耦,其核心概念包括:
核心概念
-
切面(Aspect)
指關注點的模塊化,這些關注點可能會橫切多個對象。例如,事務管理是企業級Java應用中常見的橫切關注點。在Spring AOP中,切面可以通過以下方式實現:-
通用類基于模式的方式(schema-based approach)。
-
在普通類中使用?
@Aspect
?注解(@AspectJ 注解方式)。
-
-
連接點(Join Point)
在程序執行過程中某個特定的點,例如方法調用的時間點或異常處理的時間點。在Spring AOP中,連接點僅表示方法的執行。 -
通知(Advice)
在切面的特定連接點上執行的動作。通知類型包括:-
around
(環繞通知):包裹目標方法執行。 -
before
(前置通知):在目標方法執行前觸發。 -
after
(后置通知):在目標方法執行后觸發。
許多AOP框架(包括Spring)通過攔截器模型實現通知,并維護以連接點為中心的攔截器鏈。
-
-
切點(Pointcut)
匹配連接點的斷言。通知通過切點表達式與連接點關聯,并在滿足條件的連接點上執行。Spring默認使用AspectJ切點語義,切點表達式與連接點的匹配是AOP的核心機制。 -
引入(Introduction)
向目標對象聲明額外的方法或字段。Spring允許向被通知的對象引入新接口(及其實現)。例如,可通過引入使Bean實現?IsModified
?接口以簡化緩存機制(在AspectJ社區中,引入也稱為“內部類型聲明”)。 -
目標對象(Target Object)
被一個或多個切面通知的對象,也稱為“被通知對象”。由于Spring AOP基于運行時代理實現,目標對象始終是被代理的對象。 -
AOP代理(AOP Proxy)
AOP框架創建的對象,用于實現切面契約(如通知方法的執行)。在Spring中,AOP代理可以是以下兩種類型:-
JDK動態代理(基于接口)。
-
CGLIB代理(基于子類繼承)。
-
總結
AOP通過解耦橫切關注點(如日志、事務、安全等),提升代碼復用性和可維護性。其核心思想是通過代理機制和動態織入,將公共邏輯與業務邏輯分離,最終實現高內聚、低耦合的系統設計。
任何一個系統都是由不同的組件組成的,每個組件負責一塊特定的功能。當然,會存在很多與業務無關的組件,例如日志、事務、權限等核心服務組件。這些核心服務組件經常融入到具體的業務邏輯中。如果我們為每一個具體業務邏輯操作都添加這樣的代碼,很明顯會導致代碼冗余過多。因此,我們需要將這些公共的代碼邏輯抽象出來,變成一個切面,然后注入到目標對象(具體業務)中去。正是基于這樣的一個思路實現的。通過動態代理的方式,將需要注入切面的對象進行代理。在進行調用的時候,將公共的邏輯直接添加進去,而不需要修改原有業務的邏輯代碼。只需要在原來的業務邏輯基礎之上做一些增強功能即可。