当前位置: 首页 > news >正文

Spring Boot AOP 全面解析(原理 + 实战 + 场景)

AOP(面向切面编程)是 Spring 核心特性之一,Spring Boot 对 AOP 做了轻量化封装,无需复杂配置即可快速实现日志记录、性能监控、权限校验、事务管理等横切逻辑,大幅提升代码复用性和可维护性。

一、核心概念(快速理解)
概念说明
切面(Aspect)封装横切逻辑的类(如日志切面、权限切面),是 AOP 的核心载体
连接点(JoinPoint)程序执行过程中的任意节点(如方法调用、异常抛出),Spring 仅支持方法级连接点
切入点(Pointcut)匹配需要增强的连接点(如指定包下的所有方法),通过表达式精准筛选
通知(Advice)切面的具体增强逻辑,分为 5 种类型:✅ 前置通知(Before):方法执行前执行✅ 后置通知(After):方法执行后执行(无论是否异常)✅ 返回通知(AfterReturning):方法正常返回后执行✅ 异常通知(AfterThrowing):方法抛出异常后执行✅ 环绕通知(Around):包裹方法执行,可自定义执行时机
织入(Weaving)将切面逻辑融入目标方法的过程,Spring Boot 中默认是运行时织入
二、快速上手(Spring Boot 集成 AOP)
1. 引入依赖

xml

<!-- Spring Boot AOP 核心依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. 编写切面类(实战:日志记录)

java

运行

import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; // 1. 标记为切面类 + 交给 Spring 管理 @Aspect @Component public class LogAspect { private static final Logger log = LoggerFactory.getLogger(LogAspect.class); // 2. 定义切入点:匹配 com.example.demo.service 包下所有类的所有方法 @Pointcut("execution(* com.example.demo.service.*.*(..))") public void servicePointcut() {} // 3. 前置通知:记录方法调用信息 @Before("servicePointcut()") public void beforeMethod(JoinPoint joinPoint) { String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); log.info("【前置通知】调用方法:{}.{},参数:{}", className, methodName, args); } // 4. 环绕通知:监控方法执行耗时 @Around("servicePointcut()") public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); // 执行目标方法 Object result = joinPoint.proceed(); long costTime = System.currentTimeMillis() - startTime; log.info("【环绕通知】方法 {} 执行耗时:{}ms", joinPoint.getSignature().getName(), costTime); return result; } // 5. 返回通知:记录方法返回值 @AfterReturning(value = "servicePointcut()", returning = "result") public void afterReturningMethod(JoinPoint joinPoint, Object result) { log.info("【返回通知】方法 {} 返回结果:{}", joinPoint.getSignature().getName(), result); } // 6. 异常通知:记录方法异常信息 @AfterThrowing(value = "servicePointcut()", throwing = "e") public void afterThrowingMethod(JoinPoint joinPoint, Exception e) { log.error("【异常通知】方法 {} 抛出异常:{}", joinPoint.getSignature().getName(), e.getMessage(), e); } }
3. 测试目标方法

java

运行

import org.springframework.stereotype.Service; @Service public class UserService { public String getUserInfo(Long id) { // 模拟业务逻辑 if (id <= 0) { throw new IllegalArgumentException("用户ID不能为负数"); } return "用户ID:" + id + ",姓名:张三"; } }
4. 运行效果

调用getUserInfo(1L)会输出:

plaintext

【前置通知】调用方法:com.example.demo.service.UserService.getUserInfo,参数:[1] 【环绕通知】方法 getUserInfo 执行耗时:2ms 【返回通知】方法 getUserInfo 返回结果:用户ID:1,姓名:张三

调用getUserInfo(-1L)会输出:

plaintext

【前置通知】调用方法:com.example.demo.service.UserService.getUserInfo,参数:[-1] 【异常通知】方法 getUserInfo 抛出异常:用户ID不能为负数
三、进阶用法
1. 切入点表达式(常用)
表达式类型示例说明
按方法签名匹配execution(* com.example.service.*.*(..))匹配 service 包下所有类的所有方法
按注解匹配@annotation(com.example.annotation.Log)匹配标注了 @Log 注解的方法
按包匹配within(com.example.service..*)匹配 service 包及子包下的所有类
2. 自定义注解 + AOP(更灵活)

java

运行

// 自定义注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String desc() default ""; // 日志描述 } // 切面匹配注解 @Pointcut("@annotation(com.example.demo.annotation.Log)") public void annotationPointcut() {} // 使用注解 @Service public class OrderService { @Log(desc = "创建订单") public String createOrder(String orderNo) { return "订单创建成功:" + orderNo; } }
四、注意事项
  1. 代理机制:Spring AOP 默认使用 JDK 动态代理(针对接口),无接口时自动切换为 CGLIB 代理;可通过@EnableAspectJAutoProxy(proxyTargetClass = true)强制使用 CGLIB。
  2. 内部方法调用:目标类内部调用自身方法(如A.method1()调用A.method2()),method2的切面不会生效(代理对象未被触发),可通过注入自身 Bean 解决。
  3. 性能影响:AOP 基于动态代理实现,少量切面对性能影响可忽略;大量复杂环绕通知需注意优化逻辑。
  4. 优先级:多个切面可通过@Order(n)指定执行顺序,n 越小优先级越高。
五、典型应用场景
  1. 日志审计:记录接口调用的请求参数、响应结果、操作人、操作时间。
  2. 性能监控:统计接口响应时间,识别慢接口。
  3. 权限控制:校验用户是否有接口访问权限。
  4. 事务管理:通过@Transactional(底层基于 AOP)控制事务边界。
  5. 缓存控制:缓存方法返回结果,减少重复计算。
  6. 参数校验:统一校验接口入参的合法性。
http://www.cnnetsun.cn/news/81212.html

相关文章:

  • 内存管理 - 内存泄漏 - 排查、预防策略
  • 全球服贸联盟:世界主要城市数字经济创新与知识产权发展指数报告2025(摘要)
  • 冰途缓行,雪路安驾:冰雪天气安全驾驶指南
  • DuckDB Go客户端深度开发指南:构建高性能嵌入式分析应用
  • 关于 windows 批处理文件 echo 中文后显示乱码的问题
  • 基于springboot的旅游线路定制微信小程序_u13nyaer_sf062
  • 让动态代理真正落地:在 Java 与 ABAP 里生成并持久化 Proxy 类的工程化实践
  • 用 SWE2 监听 SAP BOR 事件:以 BUS1178 产品创建为例,实时触发邮件通知与调试技巧
  • CentOS Stream 9入门学习教程,从入门到精通,Linux日志分析工具及应用 —语法详解与实战案例(17)
  • Lazy Loading、 Singleton 与 Bridge:在 JavaScript 和 ABAP 里把对象初始化写得更省、更稳、更易扩展
  • 用 ABAP 模拟 Currying:把参数绑定这件事做到极致
  • 错过这8个R语言函数,你就等于放弃了环境数据的准确性
  • CIKM‘25 | 联盟营销场景下,基于时空动态网络的两阶段传播规模预测
  • 音频格式完全指南:如何为不同场景选择最佳格式
  • DataEase 终极部署指南:从零到一的完整教程
  • 智能开发环境下的 Diagram-as-Code 实践:MCP Mermaid 技术链路拆解
  • 为什么你的多因素分析总被退稿?R语言正确姿势一次性讲清楚
  • Dio HTTP库终极指南:Flutter网络请求完整解决方案
  • 颠覆传统:新一代Vue3文档编辑器的商业价值解析
  • Habitat-Sim轻松上手:告别安装烦恼的完整指南
  • AI在企业人力资源中的应用白皮书2.0
  • DuckDB实战手册:嵌入式OLAP数据库的极速数据处理
  • RomM游戏库管理器的API密钥配置与安全实践指南
  • 实战指南:用Actix Web打造高性能微服务架构
  • 应用瘦身引擎实现容器智能分发:3分钟完成镜像压缩与动态路由
  • FLUX.1 Kontext Dev完整教程:本地部署AI图像编辑的终极方案
  • Flutter 与开源鸿蒙(OpenHarmony)的融合:跨平台开发新纪元
  • 终极指南:如何搭建个人专属音乐流媒体服务器
  • 探索Pts物理引擎:从基础粒子到复杂碰撞的艺术之旅
  • Excel插件教程:《成绩统计排名》和《SchoolTools》