SpringBoot實現(xiàn)AOP切面的三種方式
前言
Spring,SpringBoot框架憑借多種高效機制,顯著增強了代碼的功能性,并實現(xiàn)了切面編程(AOP)的精髓。其核心亮點之一,是運用動態(tài)代理技術,無需觸動源代碼即可在Bean的運行時為其動態(tài)織入額外功能,如日志記錄、安全驗證等,從而實現(xiàn)非侵入式的代碼增強。
此外,Java Agent技術,以AspectJ Weaver為代表,在JVM層面上大顯身手,攔截類加載過程并動態(tài)修改類字節(jié)碼。這一技術不僅拓展了AOP的應用場景,還蘊含了巨大的性能優(yōu)化潛力,為開發(fā)者提供了更多元化的AOP實現(xiàn)方式。
AspectJ-Maven-Plugin編譯插件則采取了另辟蹊徑的方法。它在編譯階段直接對源代碼或字節(jié)碼進行修改,確保切面邏輯與業(yè)務代碼的無縫融合。這種方式不僅優(yōu)化了程序的性能,還大幅減少了運行時的開銷,為復雜的業(yè)務邏輯提供了堅實的支撐。
1. 使用動態(tài)代理實現(xiàn)AOP
定義:AOP是一種編程范式,用于將橫切關注點(如日志、安全、事務管理等)從業(yè)務邏輯中分離出來,形成獨立的模塊。這樣可以減少代碼的冗余,提高代碼的可維護性和模塊性。
特點:
- 關注點分離:將橫切關注點與業(yè)務邏輯分離。
- 提高代碼復用:橫切關注點可以被多個地方復用。
- 減少代碼冗余:避免了在多個地方重復編寫相同的代碼。
通過動態(tài)代理方式,只需要在項目中定義@Aspect切面即可完成增強邏輯,利用CGLIB生成了代理類。
切面類代碼:
@Aspect @Component public class LoggingAspect { // 定義切點 @Pointcut("execution(* com.example.service.*.*(..))") public void serviceLayerExecution(){} // 在切點方法執(zhí)行前執(zhí)行 @Before("serviceLayerExecution()") public void logBeforeServiceMethod(JoinPoint joinPoint) { System.out.println("Before method: " + joinPoint.getSignature().getName()); } // 可以繼續(xù)添加其他類型的通知,如@After、@AfterReturning、@AfterThrowing、@Around等 }
服務類代碼:
@Service public class UserService { public void save() { System.out.println("Saving user..."); } }
2. 使用Java Agent技術實現(xiàn)AOP(AspectJ Weaver)
定義:Java Agent技術允許開發(fā)者在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼。這種技術通過Java Instrumentation API實現(xiàn)。
應用場景:
- AOP支持:利用Java Agent技術(如AspectJ Weaver),可以在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼,實現(xiàn)更廣泛的AOP支持。
- 性能優(yōu)化:通過動態(tài)修改字節(jié)碼,可以優(yōu)化類的執(zhí)行性能。
- 動態(tài)監(jiān)控與調(diào)試:在類加載時注入監(jiān)控或調(diào)試代碼。
特點:
- 廣泛支持:支持在JVM層面進行類加載的攔截和修改。
- 配置復雜:相比其他AOP實現(xiàn)方式,配置可能更為復雜。
使用Java Agent技術涉及到更復雜的配置,
包括編寫自定義的Agent類,主要步驟包括將AspectJ Weaver作為Java Agent運行。下面看看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)代理相同的切點和通知定義 @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
通過以上實現(xiàn), 我們的SpringBoot業(yè)務代碼UserService 被增強了,同時UserService并沒有創(chuàng)建代理。通過反編譯查看UserService編譯后的字節(jié)碼也沒有任何的變化。Agent的原理就在進行類加載時對類進行增強。
3. 使用AspectJ編譯時織入實現(xiàn)AOP
定義:AspectJ-Maven-Plugin是一個Maven編譯插件,用于在編譯時直接修改源代碼或字節(jié)碼,以集成切面邏輯。
應用場景:
- AOP集成:通過編譯時修改字節(jié)碼,實現(xiàn)切面邏輯與業(yè)務代碼的無縫集成。
- 性能優(yōu)化:由于是在編譯階段進行代碼的增強,因此減少了運行時的開銷,提升了性能。
特點:
- 性能最佳:編譯時增強減少了運行時的開銷。
- 深度集成:切面邏輯與業(yè)務代碼無縫集成。
- 需要重新編譯:每當切面邏輯或業(yè)務代碼發(fā)生變化時,都需要重新編譯項目。
SpringBoot中,動態(tài)代理的方式,通過對目標類生成代理,在執(zhí)行目標方法前執(zhí)行增強邏輯Advice,這種方式多少對性能是有影響的。而編譯插件方式是在編譯時增強,性能最佳,深度集成,減少運行時開銷。
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>
注意:如果切面類位于同一項目中,不需要單獨指定aspectLibraries
。
切面類代碼(與動態(tài)代理相同,不需要@Component
注解):
…省略很多代碼…
總結
- AOP:是一種編程范式,用于將橫切關注點從業(yè)務邏輯中分離出來,提高代碼的可維護性和模塊性。
- Java Agent:在JVM層面攔截類加載過程,動態(tài)修改類字節(jié)碼,支持廣泛的AOP場景,但配置可能較為復雜。
- AspectJ-Maven-Plugin:是一個Maven編譯插件,通過編譯時修改字節(jié)碼來集成切面邏輯,性能最佳,但需要重新編譯項目。
到此這篇關于SpringBoot實現(xiàn)AOP切面的三種方式的文章就介紹到這了,更多相關SpringBoot實現(xiàn)AOP切面內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaWeb連接數(shù)據(jù)庫MySQL的操作技巧
數(shù)據(jù)庫是編程中重要的一部分,它囊括了數(shù)據(jù)操作,數(shù)據(jù)持久化等各方面。在每一門編程語言中都占有相當大的比例。本次,小編以MySQL為例,使用mvc編程思想,給大家講解下javaweb對數(shù)據(jù)庫的操作2017-02-02JVM性能調(diào)優(yōu)之運行時參數(shù)小結
jvm是java的運行環(huán)境,在jvm中有很多的參數(shù)可以進行設置,本文主要介紹了JVM性能調(diào)優(yōu)之運行時參數(shù)小結,具有一定的參考價值,感興趣的可以了解一下2024-04-04分享Spring?Cloud?OpenFeign?的五個優(yōu)化技巧
這篇文章主要分享的是Spring?Cloud?OpenFeign?的五個優(yōu)化技巧,OpenFeign?是?Spring?官方推出的一種聲明式服務調(diào)用和負載均衡組件,更多相關內(nèi)容需要的小伙伴可以參考一下2022-05-05SpringBoot實現(xiàn)輕量級動態(tài)定時任務管控及組件化的操作步驟
文章介紹了一種在SpringBoot中實現(xiàn)動態(tài)定時任務的解決方案,基于COLA架構理論,封裝到了組件層,該組件支持類級別和方法級別的定時任務注冊,并提供了易用性和擴展性,組件使用Maven形式引入,并且可以通過YAML配置文件進行設置,感興趣的朋友一起看看吧2024-11-11