深入解析:Spring Boot 集成 Spring AOP 的实战指南

news/2025/2/25 21:52:27/文章来源:https://www.cnblogs.com/java-note/p/18737361

1. 添加依赖:为项目注入 AOP 的灵魂

在 Spring Boot 的世界里,依赖管理是通过 pom.xml 文件来精心编排的。为了引入 Spring AOP 的核心功能,确保项目能够无缝地利用 AOP 提供的强大特性,我们需要在 pom.xml 中添加相应的依赖项。幸运的是,Spring Boot 的默认依赖管理已经非常完善,spring-boot-starter-aop 通常会自动包含在 spring-boot-starter 中。这意味着在大多数情况下,你无需手动添加任何额外的依赖即可开始使用 AOP 功能。然而,如果你希望更加明确地声明对 AOP 的依赖,或者需要对依赖版本进行定制化管理,可以手动在 pom.xml 文件中加入以下依赖配置:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

这段依赖声明不仅为项目引入了 Spring AOP 的核心功能,还为后续的开发工作奠定了坚实的基础。它确保了项目能够无缝地利用 AOP 提供的强大特性,从而让你能够更加专注于业务逻辑的实现,而无需担心底层的实现细节。通过这种方式,你为项目注入了 AOP 的灵魂,使其具备了处理横切关注点的能力。


2. 创建切面类(Aspect):定义 AOP 的核心逻辑

切面类是 Spring AOP 中的核心组成部分,它承载着 AOP 的核心逻辑,定义了哪些操作需要被拦截,以及在拦截点上应该执行什么样的额外逻辑。一个切面类通常由两部分组成:切点(Pointcut)和通知(Advice)。切点用于指定需要被拦截的方法或类,而通知则是在拦截点上执行的具体逻辑。

在 Spring 中,切面类需要使用 @Aspect 注解进行标记,以表明这是一个 AOP 切面。同时,为了确保切面类能够被 Spring 容器正确管理,我们还需要使用 @Component 注解将其声明为一个 Spring Bean。这样,Spring 容器就能够自动扫描并加载该切面类,使其能够参与到项目的运行过程中。

以下是一个简单的切面类示例,展示了如何定义一个基本的切面类:

package com.example.demo.aspect;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class MyAspect {// 定义切点:匹配 com.example.demo.controller 包下所有类的所有方法@Pointcut("execution(* com.example.demo.controller.*.*(..))")public void pointcut() {}// 定义通知:在方法执行前打印日志@Before("pointcut()")public void beforeAdvice() {System.out.println("Before method execution: Logging request");}
}

在这个示例中,@Aspect 注解标记了这是一个切面类,而 @Component 注解则确保了它能够被 Spring 容器管理。@Pointcut 注解定义了一个切点,其表达式 execution(* com.example.demo.controller.*.*(..)) 表示匹配 com.example.demo.controller 包下所有类的所有方法。@Before 注解则定义了一个前置通知,它会在匹配的方法执行之前执行,并打印一条日志信息。通过这种方式,切面类将业务逻辑与横切关注点分离,实现了代码的高内聚和低耦合。


3. 定义切点(Pointcut):精准定位拦截目标

切点是 AOP 中的关键概念之一,它决定了哪些方法或类会被 AOP 拦截。切点表达式使用 AspectJ 的语法来定义,这种语法提供了强大的灵活性和表达能力,能够让你以非常精确的方式指定拦截的目标。通过合理地定义切点表达式,你可以精准地控制哪些代码会被 AOP 拦截,从而确保 AOP 的逻辑能够准确地应用到需要的地方,而不会对其他无关的代码产生影响。

以下是一些常见的切点表达式示例及其含义:

  • execution(* com.example.demo.controller.*.*(..)):匹配 com.example.demo.controller 包下所有类的所有方法。
  • execution(* com.example.demo.service.*.*(..)):匹配 com.example.demo.service 包下所有类的所有方法。
  • execution(* com.example.demo.service.UserService.*(..)):匹配 UserService 类的所有方法。
  • execution(* com.example.demo.service.UserService.saveUser(..)):匹配 UserService 类的 saveUser 方法。

通过这些表达式,你可以轻松地定义出符合项目需求的切点,从而让 AOP 的拦截机制能够精准地作用于目标代码。这种精准的拦截能力是 AOP 的一大优势,它使得开发者能够将通用逻辑集中管理,而无需在每个业务逻辑中重复编写相同的代码。


4. 定义通知(Advice):实现拦截点的逻辑

通知是切面类中定义的具体逻辑,它决定了在拦截点上应该执行什么样的操作。Spring AOP 提供了多种通知类型,每种通知类型都有其特定的用途和执行时机。以下是一些常见的通知类型及其使用场景:

  • 前置通知(@Before):在方法执行之前执行。通常用于日志记录、权限校验等场景。
  • 后置通知(@After):在方法执行之后执行,无论方法是否成功。适用于清理资源、记录方法执行时间等操作。
  • 返回通知(@AfterReturning):在方法成功返回后执行。可以用于处理方法的返回值,例如对返回值进行加密或格式化。
  • 异常通知(@AfterThrowing):在方法抛出异常时执行。可用于捕获异常、记录错误日志或进行异常处理。
  • 环绕通知(@Around):在方法执行前后都可以执行,可以控制方法是否执行。这是最强大的通知类型,适用于需要完全控制方法执行流程的场景,例如实现缓存逻辑或事务管理。

以下是一个完整的切面类示例,展示了如何定义多种通知类型:

@Aspect
@Component
public class MyAspect {// 前置通知@Before("pointcut()")public void beforeAdvice() {System.out.println("Before method execution: Logging request");}// 后置通知@After("pointcut()")public void afterAdvice() {System.out.println("After method execution: Logging response");}// 返回通知@AfterReturning(pointcut = "pointcut()", returning = "result")public void afterReturningAdvice(Object result) {System.out.println("Method returned with result: " + result);}// 异常通知@AfterThrowing(pointcut = "pointcut()", throwing = "ex")public void afterThrowingAdvice(Exception ex) {System.out.println("Exception occurred: " + ex.getMessage());}// 环绕通知@Around("pointcut()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before method execution: Logging request");Object result = joinPoint.proceed(); // 执行原方法System.out.println("After method execution: Logging response");return result;}
}

在这个示例中,我们定义了五种不同类型的通知,每种通知都对应着不同的执行时机和用途。通过合理地使用这些通知类型,你可以实现各种复杂的 AOP 功能,从而满足项目中的各种需求。这种灵活的通知机制是 AOP 的核心优势之一,它使得开发者能够以一种声明式的方式处理横切关注点,而无需在业务逻辑中嵌入复杂的代码。


5. 测试 AOP 功能:验证集成效果

完成切面类的定义后,接下来需要通过实际的代码测试来验证 AOP 功能是否正确集成到项目中。为了进行测试,你可以创建一个简单的 Controller 或 Service 类,并在其中定义一些方法来触发 AOP 的拦截逻辑。

以下是一个简单的 Controller 类示例,用于测试 AOP 功能:

package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TestController {@GetMapping("/test")public String test() {return "Hello, AOP!";}
}

运行项目后,访问 /test 接口,观察控制台输出是否符合预期。如果一切正常,你应该能够在控制台中看到由 AOP 切面类打印的日志信息,例如方法执行前的日志、方法执行后的日志等。这表明 AOP 功能已经成功集成到项目中,并且能够按照预期工作。通过这种方式,你可以确保 AOP 的逻辑正确地作用于目标方法,从而为项目的稳定运行提供保障。


6. 注意事项:确保 AOP 集成的稳定性和性能

在使用 Spring AOP 时,还需要注意以下几点,以确保 AOP 功能的稳定性和性能:

  1. 切点表达式的准确性:切点表达式是 AOP 的核心,必须确保其能够准确匹配目标方法。如果切点表达式定义不准确,可能会导致通知无法正确执行,或者对不必要的方法进行拦截,从而影响系统的性能。
  2. 依赖注入:在切面类中,如果需要使用 Spring 管理的 Bean,可以通过 @Autowired 注解进行注入。这样可以让你在通知中访问其他组件的功能,从而实现更加复杂的逻辑。
  3. 性能影响:AOP 会引入额外的调用开销,尤其是在使用环绕通知时,可能会对方法的执行性能产生一定的影响。因此,在使用 AOP 时,应尽量避免在高频调用的方法上使用复杂的 AOP 逻辑,以免对系统性能造成负面影响。
  4. Aspect 优先级:如果项目中存在多个切面类,可能会出现多个切面类同时对同一个方法进行拦截的情况。此时,可以通过 @Order 注解来指定切面类的优先级,值越小优先级越高。这样可以确保通知的执行顺序符合预期,避免出现不可预测的行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/889777.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[BUUCTF]刷题记录PWN——ez_pz_hackover_2016

静态分析比较重要的函数,一个strlen可以利用\x00来绕过,然后对输入的字符串进行检查,最后进入vulnmemcoy: C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。也就是说,vuln里的memcpy函数会把,我们输入的内容取…

基于信息论的高动态范围图像评价算法matlab仿真

1.程序功能描述 基于信息论的高动态范围图像评价算法matlab仿真,利用一种自然图像的概率模型对图像的熵与成像动态范围之间的关系进行了数值模拟,得到了具有普遍意义上的理想成像动态范围的计算公式,公式指出了对自然景物完善成像所需的最大动态范围;给出了图像熵与动态…

BloomFilter详解

目录BloomFilter 原理:问题引入:黑名单管理程序哈希、哈希函数BloomFilter :3.4 BloomFilter 的缺陷、改进:代码实现黑名单blacklist.py:普通的实现方法set.py:哈希函数hash.py:4.4 BloomFilter 实现方法bloomfilter.py: BloomFilter 原理: ​ 我们将从哈希函数开始…

【ABP】项目示例(4)——领域服务

领域服务 在上一章节中,已经完成了仓储的设计,在这一章节中,实现领域服务,即业务的核心逻辑 领域服务主要处理特定领域的业务逻辑,对内协调和整合聚合根与各个实体的业务关系,对外作为业务的边界,供应用服务组合来提供完整复杂的功能 规约 在名称为General.Backend.Doma…

YOLOv10 解析与地平线 征程 6模型量化

一,YOLOv10 解析 1.简介 近些年来,研究人员对 YOLO 的架构设计、优化目标、数据增强策略等进行了探索,取得了显著进展。然而,后处理对非极大值抑制(NMS)的依赖阻碍了 YOLO 的端到端部署,并对推理延迟产生不利影响。此外,YOLO 中各个组件的设计缺乏全面彻底的检查,导致…

SemanticKernel之Chat

去年写过几过几篇关于SemanticKernel的文章,由于正式发布的版本与之前的版本变化较大,加上前的东京《生成式AI应用开发》活动,想把演示的Demo逐一分享出来,的以再次开启SemanticKernel系统。下面是一个Chat的例子,用户提问,如果本地有固定数据能对应,直接返回,如果没有…

7、添加特效

去除画面logo 复制一份 拖动模糊特效到复制的片段中 右键分离音频或者快捷键【ctrl+shift+s】 删除音频 添加原创特效,特效随机 有音乐的去除音乐 适当拖动放大 调整透明度 开幕特效 三秒 调整参数后,复制双份 画面特效和人物特效二选一 画面特效需要修改参数

Prompt升级

前两篇关于Prompt的文章分别从提示词规则建议和具体框架角度说明了一下Prompt的使用技巧,接下来可以说是对框架式提示词的的进一步升级——结构化提示词。 结构化定义: 对信息进行组织,使其遵循特定的模式和规则,从而方便有效理解信息。 结构化提示词语法:这个结构支持 Mark…

Spring复习-事务

事务概述 Spring事务编程概述 事务是开发中必不可少的东西,使用JDBC开发时,我们使用connnection对事务进行控制,使用MvBatis时,我们使用SqlSession对事务进行控制,缺点显而易见,当我们切换数据库访问技术时,事务控制的方式总会变化,Spring 就将这些技术基础上,提供了统…

Prompt进阶

在Prompt入门里,我们分享了OpenAI官方给出的提示词建议,但这些建议基本上是指导性的,方向性的,概念性的,虽然对我们编写提示词有很大帮助,但究竟我们的提示词好还是不好,效率怎么性,很大程度上要看每个人的理解,和提示词输出。那么有没有一个可操作性的,方法论的,谁…

P1174 打砖块

链接 https://www.luogu.com.cn/problem/P1174 思路刚开始的思路:设置dp[i][j]:前i列使用了j颗子弹,那么递推dpi,j=max(dpi,j,dpi-1,k+maxj-k),然后统计在第i列使用了j-k颗子弹会多出来多少颗,把这些遍历加到前面,见代码。喜提70pts。但是搞不懂哪里错了。 看了评论区的dp:70…

redis - [06] redis-benchmark性能测试

题记部分 001 || 参数含义 002 || 测试100个并发,100000个请求 启动redis-server redis-server /etc/redis.conf 进行性能测试 redis-benchmark -h localhost -p 6379 -c 100 -n 100000