SpringBoot集成AOP的代碼示例
1.什么是AOP?
AOP(Aspect Oriented Programming,面向切面編程)是一種編程范式,它旨在將橫切關(guān)注點(cross-cutting concerns)從應(yīng)用程序的業(yè)務(wù)邏輯中分離出來。橫切關(guān)注點是那些在多個模塊中重復(fù)出現(xiàn)的功能,如日志記錄、性能監(jiān)控、事務(wù)管理、安全控制等。AOP允許開發(fā)者將這些關(guān)注點模塊化,并在不影響應(yīng)用程序主要功能的情況下,將它們編織到應(yīng)用程序的各個點上。
AOP的關(guān)鍵概念
- 切面(Aspect):封裝了橫切關(guān)注點的模塊。它描述了要執(zhí)行的附加行為以及該行為應(yīng)該被應(yīng)用到哪些連接點上。
- 連接點(Joinpoint):程序執(zhí)行過程中的某個點,如方法調(diào)用或異常拋出。
- 通知(Advice):切面在特定的連接點上執(zhí)行的動作,如“before”、“after”、“around”等。
- 切入點(Pointcut):匹配連接點的表達(dá)式,定義了切面的哪個部分會被應(yīng)用到哪些連接點上。
- 目標(biāo)對象(Target Object):被一個或多個切面所通知的對象。
- 代理(Proxy):由AOP框架創(chuàng)建的對象,用來攔截目標(biāo)對象上的方法調(diào)用。
AOP的實現(xiàn)方式
AOP可以通過以下幾種方式實現(xiàn):
- 基于代理的AOP:
- JDK動態(tài)代理:適用于實現(xiàn)接口的情況,利用反射機制生成代理類。
- CGLIB:使用字節(jié)碼技術(shù)生成子類,適用于未實現(xiàn)接口的情況。
- 基于字節(jié)碼操作的AOP:
- AspectJ:在編譯期或運行期通過修改字節(jié)碼來實現(xiàn)切面的編織,可以更細(xì)粒度地控制切面的織入。
- 聲明式AOP:
- Spring AOP:使用XML配置或注解(如
@Aspect
、@Before
、@After
、@Around
等)來定義切面和切入點,然后在運行時通過動態(tài)代理實現(xiàn)切面的編織。
- Spring AOP:使用XML配置或注解(如
實現(xiàn)AOP的關(guān)鍵技術(shù)
- 動態(tài)代理:在運行時動態(tài)創(chuàng)建代理對象,代理對象在調(diào)用目標(biāo)方法前后可以執(zhí)行額外的操作。
- 字節(jié)碼操作庫:如ASM、ByteBuddy等,用于生成或修改字節(jié)碼,實現(xiàn)在類的加載之前或運行時修改類的行為。
- 元數(shù)據(jù)驅(qū)動:使用注解或XML配置來定義切面、切入點和通知,便于配置和管理AOP的規(guī)則。
AOP的主要優(yōu)點是能夠減少業(yè)務(wù)邏輯中的重復(fù)代碼,提高代碼的模塊化程度,使得關(guān)注點更加集中,同時也提高了代碼的可維護(hù)性和可讀性。在實際應(yīng)用中,AOP經(jīng)常被用于企業(yè)級應(yīng)用開發(fā),如在Spring框架中廣泛使用。
2.代碼工程
實驗?zāi)繕?biāo)
采用@aspect注解來實現(xiàn)aop
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springboot-demo</artifactId> <groupId>com.et</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>aspect</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> </dependencies> </project>
controller
package com.et.aspect.controller; import com.et.aspect.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController public class HelloWorldController { @Autowired TestService testService; @RequestMapping("/hello") public Map<String, Object> showHelloWorld(){ Map<String, Object> map = new HashMap<>(); String str= testService.sayHello("liming"); map.put("msg",str); return map; } }
service
package com.et.aspect.service; public interface TestService { public String sayHello(String name) ; } package com.et.aspect.service.impl; import com.et.aspect.service.TestService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** * @author liuhaihua * @version 1.0 * @ClassName TestServiceImpl * @Description todo * @date 2024/09/05/ 9:21 */ @Service @Slf4j public class TestServiceImpl implements TestService { @Override public String sayHello(String name) { String sss="hello,"+name; log.info(sss); return sss; } }
aspect
@Aspect:作用是把當(dāng)前類標(biāo)識為一個切面供容器讀取
@Pointcut:定義切入點,Pointcut是植入Advice的觸發(fā)條件。 每個Pointcut的定義包括2部分,一是表達(dá)式,二是方法簽名。方法簽名必須是 public及void型。 可以將Pointcut中的方法看作是一個被Advice引用的助記符,因為表達(dá)式不直觀,因此我們可以通過方法簽名的方式為 此表達(dá)式命名。 因此Pointcut中的方法只需要方法簽名,而不需要在方法體內(nèi)編寫實際代碼。
@Around:環(huán)繞增強,相當(dāng)于MethodInterceptor(方法攔截器)
@AfterReturning:后置增強,相當(dāng)于AfterReturningAdvice,方法正常退出時執(zhí)行
@Before:標(biāo)識一個前置增強方法,相當(dāng)于BeforeAdvice的功能,相似功能的還有
@AfterThrowing:異常拋出增強,相當(dāng)于ThrowsAdvice(異常通知)
@After: final增強,不管是拋出異?;蛘哒M顺龆紩?zhí)行
@Pointcut("execution(* com.et.aspect.service..*.*(..))") public void aopPoint() { } @Before("aopPoint()") public void doBefore(JoinPoint point) throws Throwable { log.info("before ...."); } @After("aopPoint()") public void doAfter(JoinPoint point) throws Throwable { log.info("after ...."); }
以上只是一些關(guān)鍵代碼,所有代碼請參見下面代碼倉庫
代碼倉庫
3.測試
啟動Spring Boot應(yīng)用程序
訪問http://127.0.0.1:8088/hello
查看日志如下
2024-09-05 21:52:12.926 INFO 51009 --- [nio-8088-exec-1] com.et.aspect.aspect.TaskAspect : before .... 2024-09-05 21:52:12.939 INFO 51009 --- [nio-8088-exec-1] c.e.aspect.service.impl.TestServiceImpl : hello,liming 2024-09-05 21:52:12.939 INFO 51009 --- [nio-8088-exec-1] com.et.aspect.aspect.TaskAspect : after ....
以上就是Spring Boot集成AOP的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot集成AOP的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring\SpringBoot配置連接數(shù)據(jù)庫的方法
最近在學(xué)習(xí)SpringBoot,第一步就是要配置數(shù)據(jù)庫,本文詳細(xì)的介紹了Spring\SpringBoot配置連接數(shù)據(jù)庫的方法,有需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06Spring中網(wǎng)絡(luò)請求客戶端WebClient的使用詳解
作為替代,Spring 官方已在 Spring 5 中引入了 WebClient 作為非阻塞式 Reactive HTTP 客戶端,本文將通過樣例演示如何使用 WebClient,希望對大家有所幫助2024-04-04基于String和List<String>間的相互轉(zhuǎn)換方式
這篇文章主要介紹了基于String和List間的相互轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05