SpringBoot實(shí)現(xiàn)AOP切面的三種方式
前言
Spring,SpringBoot框架憑借多種高效機(jī)制,顯著增強(qiáng)了代碼的功能性,并實(shí)現(xiàn)了切面編程(AOP)的精髓。其核心亮點(diǎn)之一,是運(yùn)用動態(tài)代理技術(shù),無需觸動源代碼即可在Bean的運(yùn)行時為其動態(tài)織入額外功能,如日志記錄、安全驗(yàn)證等,從而實(shí)現(xiàn)非侵入式的代碼增強(qiáng)。
此外,Java Agent技術(shù),以AspectJ Weaver為代表,在JVM層面上大顯身手,攔截類加載過程并動態(tài)修改類字節(jié)碼。這一技術(shù)不僅拓展了AOP的應(yīng)用場景,還蘊(yùn)含了巨大的性能優(yōu)化潛力,為開發(fā)者提供了更多元化的AOP實(shí)現(xiàn)方式。
AspectJ-Maven-Plugin編譯插件則采取了另辟蹊徑的方法。它在編譯階段直接對源代碼或字節(jié)碼進(jìn)行修改,確保切面邏輯與業(yè)務(wù)代碼的無縫融合。這種方式不僅優(yōu)化了程序的性能,還大幅減少了運(yùn)行時的開銷,為復(fù)雜的業(yè)務(wù)邏輯提供了堅實(shí)的支撐。
1. 使用動態(tài)代理實(shí)現(xiàn)AOP
定義:AOP是一種編程范式,用于將橫切關(guān)注點(diǎn)(如日志、安全、事務(wù)管理等)從業(yè)務(wù)邏輯中分離出來,形成獨(dú)立的模塊。這樣可以減少代碼的冗余,提高代碼的可維護(hù)性和模塊性。
特點(diǎn):
- 關(guān)注點(diǎn)分離:將橫切關(guān)注點(diǎn)與業(yè)務(wù)邏輯分離。
- 提高代碼復(fù)用:橫切關(guān)注點(diǎn)可以被多個地方復(fù)用。
- 減少代碼冗余:避免了在多個地方重復(fù)編寫相同的代碼。
通過動態(tài)代理方式,只需要在項(xiàng)目中定義@Aspect切面即可完成增強(qiáng)邏輯,利用CGLIB生成了代理類。
切面類代碼:
@Aspect
@Component
public class LoggingAspect {
// 定義切點(diǎn)
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayerExecution(){}
// 在切點(diǎn)方法執(zhí)行前執(zhí)行
@Before("serviceLayerExecution()")
public void logBeforeServiceMethod(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
// 可以繼續(xù)添加其他類型的通知,如@After、@AfterReturning、@AfterThrowing、@Around等
}
服務(wù)類代碼:
@Service
public class UserService {
public void save() {
System.out.println("Saving user...");
}
}
2. 使用Java Agent技術(shù)實(shí)現(xiàn)AOP(AspectJ Weaver)
定義:Java Agent技術(shù)允許開發(fā)者在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼。這種技術(shù)通過Java Instrumentation API實(shí)現(xiàn)。
應(yīng)用場景:
- AOP支持:利用Java Agent技術(shù)(如AspectJ Weaver),可以在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼,實(shí)現(xiàn)更廣泛的AOP支持。
- 性能優(yōu)化:通過動態(tài)修改字節(jié)碼,可以優(yōu)化類的執(zhí)行性能。
- 動態(tài)監(jiān)控與調(diào)試:在類加載時注入監(jiān)控或調(diào)試代碼。
特點(diǎn):
- 廣泛支持:支持在JVM層面進(jìn)行類加載的攔截和修改。
- 配置復(fù)雜:相比其他AOP實(shí)現(xiàn)方式,配置可能更為復(fù)雜。
使用Java Agent技術(shù)涉及到更復(fù)雜的配置,
包括編寫自定義的Agent類,主要步驟包括將AspectJ Weaver作為Java Agent運(yùn)行。下面看看aop.xml和切面類的配置。
aop.xml(放在META-INF目錄下):
<aspectj>
<weaver>
<!-- 指定哪些包下的類需要被織入 -->
<include within="com.example.service..*"/>
</weaver>
<aspects>
<!-- 指定切面類,可定義多個 -->
<aspect name="com.example.aspect.LoggingAspect"/>
</aspects>
</aspectj>
切面類代碼(與動態(tài)代理類似,但不需要@Component注解):
@Aspect
public class LoggingAspect {
// 與動態(tài)代理相同的切點(diǎn)和通知定義
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayerExecution(){}
@Before("serviceLayerExecution()")
public void logBeforeServiceMethod(JoinPoint joinPoint) {
// 日志記錄邏輯
}
}
** 指定JVM參數(shù) **
使用Java Agent時,需要在JVM啟動參數(shù)中指定AspectJ Weaver的jar包
-javaagent:d:/maven/org/aspectj/aspectjweaver/1.9.7/aspectjweaver-1.9.7.jar
通過以上實(shí)現(xiàn), 我們的SpringBoot業(yè)務(wù)代碼UserService 被增強(qiáng)了,同時UserService并沒有創(chuàng)建代理。通過反編譯查看UserService編譯后的字節(jié)碼也沒有任何的變化。Agent的原理就在進(jìn)行類加載時對類進(jìn)行增強(qiáng)。
3. 使用AspectJ編譯時織入實(shí)現(xiàn)AOP
定義:AspectJ-Maven-Plugin是一個Maven編譯插件,用于在編譯時直接修改源代碼或字節(jié)碼,以集成切面邏輯。
應(yīng)用場景:
- AOP集成:通過編譯時修改字節(jié)碼,實(shí)現(xiàn)切面邏輯與業(yè)務(wù)代碼的無縫集成。
- 性能優(yōu)化:由于是在編譯階段進(jìn)行代碼的增強(qiáng),因此減少了運(yùn)行時的開銷,提升了性能。
特點(diǎn):
- 性能最佳:編譯時增強(qiáng)減少了運(yùn)行時的開銷。
- 深度集成:切面邏輯與業(yè)務(wù)代碼無縫集成。
- 需要重新編譯:每當(dāng)切面邏輯或業(yè)務(wù)代碼發(fā)生變化時,都需要重新編譯項(xiàng)目。
SpringBoot中,動態(tài)代理的方式,通過對目標(biāo)類生成代理,在執(zhí)行目標(biāo)方法前執(zhí)行增強(qiáng)邏輯Advice,這種方式多少對性能是有影響的。而編譯插件方式是在編譯時增強(qiáng),性能最佳,深度集成,減少運(yùn)行時開銷。
pom.xml中添加AspectJ-Maven-Plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>com.example</groupId>
<artifactId>your-aspect-library</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
<goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
注意:如果切面類位于同一項(xiàng)目中,不需要單獨(dú)指定aspectLibraries。
切面類代碼(與動態(tài)代理相同,不需要@Component注解):
…省略很多代碼…
總結(jié)
- AOP:是一種編程范式,用于將橫切關(guān)注點(diǎn)從業(yè)務(wù)邏輯中分離出來,提高代碼的可維護(hù)性和模塊性。
- Java Agent:在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼,支持廣泛的AOP場景,但配置可能較為復(fù)雜。
- AspectJ-Maven-Plugin:是一個Maven編譯插件,通過編譯時修改字節(jié)碼來集成切面邏輯,性能最佳,但需要重新編譯項(xiàng)目。
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)AOP切面的三種方式的文章就介紹到這了,更多相關(guān)SpringBoot實(shí)現(xiàn)AOP切面內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用場景分析
- AOP在SpringBoot項(xiàng)目中的使用場景解讀
- SpringBoot整合Jasypt使用自定義注解+AOP實(shí)現(xiàn)敏感字段加解密
- Springboot如何正確使用AOP問題
- springboot接口服務(wù),防刷、防止請求攻擊,AOP實(shí)現(xiàn)方式
- SpringBoot3利用AOP實(shí)現(xiàn)IP黑名單功能
- springbootAOP定義切點(diǎn)獲取/修改請求參數(shù)方式
- SpringBoot中使用AOP實(shí)現(xiàn)日志記錄功能
- SpringBoot AOP如何配置全局事務(wù)
- JAVA中Spring Boot的AOP切面編程是什么,如何使用?(實(shí)例代碼)
相關(guān)文章
利用SpringBoot實(shí)現(xiàn)高效的文件分塊上傳方案
在互聯(lián)網(wǎng)應(yīng)用中,大文件上傳是一個常見而棘手的挑戰(zhàn),傳統(tǒng)的單文件上傳方式在面對大文件時經(jīng)常面臨超時、內(nèi)存溢出等問題,本文將深入探討如何利用Spring Boot實(shí)現(xiàn)高效的分塊上傳方案,解決大文件傳輸痛點(diǎn),需要的朋友可以參考下2025-06-06
fastJson泛型如何轉(zhuǎn)換的實(shí)現(xiàn)
這篇文章主要介紹了fastJson泛型如何轉(zhuǎn)換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Java調(diào)用參數(shù)類型是application/x-www-form-urlencoded的API問題
在使用Postman進(jìn)行接口測試時,對于POST請求,需將請求頭設(shè)置為application/x-www-form-urlencoded,并將參數(shù)轉(zhuǎn)為String類型,通常在GET請求中,參數(shù)直接拼接在URL后,本文通過具體實(shí)例,詳細(xì)講解了參數(shù)處理的方法,適合API開發(fā)者參考2024-09-09
解決SpringAop內(nèi)部調(diào)用時不經(jīng)過代理類的問題
這篇文章主要介紹了解決SpringAop內(nèi)部調(diào)用時不經(jīng)過代理類的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

