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

Spring AOP 进阶实战:从日志到权限/链路追踪/限流(真正企业用法)

一、前言

上一篇

Spring AOP 从原理到实战(结合事务彻底搞懂)

我们已经搞懂了:

✔ AOP 原理
✔ @Before / @After / @Around 的区别
✔ 事务为什么用 AOP

但是很多人学完之后,会有一个问题:AOP 到底在项目里怎么用?

这一篇,我们不再讲“语法”,而是讲:

企业项目中,AOP 真正用在哪些地方?什么时候用?


二、AOP 的本质再理解(关键)

先记住一句话:

AOP = 把“非业务逻辑”从业务代码里抽离

比如:

类型是否业务
下单、注册✅ 业务
打日志❌ 非业务
权限校验❌ 非业务
限流❌ 非业务
链路追踪❌ 非业务

👉 所以:

AOP 专门处理:所有“横切关注点”

三、企业中 AOP 常见 4 大场景

这一节是重点 👇


1️⃣ 日志 AOP(必备)

👉 使用时机:
所有接口调用都要记录: ✔ 参数 ✔ 返回值 ✔ 耗时 ✔ 异常
👉 为什么用 AOP?
不可能每个 Controller 都写 log

✅ 推荐写法(Around)
@Aspect @Component @Slf4j public class LogAspect { @Around("execution(* com.xxx.modules..controller..*(..))") public Object log(ProceedingJoinPoint jp) throws Throwable { long start = System.currentTimeMillis(); String method = jp.getSignature().toShortString(); try { Object result = jp.proceed(); long cost = System.currentTimeMillis() - start; log.info("接口:{},耗时:{}ms,返回:{}", method, cost, result); return result; } catch (Throwable e) { log.error("接口异常:{}", method, e); throw e; } } }

什么时候用?
✔ 所有项目(必须) ✔ 第一个 AOP

2️⃣ TraceId(链路追踪)


👉 使用时机:
当日志“看不懂”的时候

例如:

多个用户同时请求 → 日志混在一起

✅ 解决方案:
给每个请求一个唯一 ID

示例:
@Aspect @Component public class TraceIdAspect { @Around("execution(* com.xxx.modules..*(..))") public Object trace(ProceedingJoinPoint jp) throws Throwable { String traceId = UUID.randomUUID().toString().replace("-", ""); MDC.put("traceId", traceId); try { return jp.proceed(); } finally { MDC.remove("traceId"); } } }

logback 配置:
<pattern>%d{HH:mm:ss} [%X{traceId}] %-5level %logger - %msg%n</pattern>

什么时候用?
✔ 有多个接口 ✔ 有并发 ✔ 开始调试问题 ✔ 面试加分项

3️⃣ 权限控制 AOP(RBAC 基础


👉 使用时机:
接口需要权限控制

❌ 不推荐写法:
if (!isAdmin()) { throw new RuntimeException("没权限"); }

👉 到处都是权限判断 ❗


✅ AOP 写法

定义注解:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CheckPermission { String value(); }

AOP:

@Aspect @Component public class PermissionAspect { @Around("@annotation(checkPermission)") public Object check(ProceedingJoinPoint jp, CheckPermission checkPermission) throws Throwable { String permission = checkPermission.value(); if (!hasPermission(permission)) { throw new RuntimeException("没有权限:" + permission); } return jp.proceed(); } }

使用:

@CheckPermission("user:add") @PostMapping("/add") public String addUser() { return "ok"; }
什么时候用?
✔ 有登录系统 ✔ 有角色权限(admin/user) ✔ 企业项目必备

4️⃣ 限流 AOP(高并发保护)


👉 使用时机:
接口被频繁调用 / 防刷 / 防攻击

示例:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RateLimit { int limit(); }

@Aspect @Component public class RateLimitAspect { private final Map<String, AtomicInteger> counter = new ConcurrentHashMap<>(); @Around("@annotation(rateLimit)") public Object limit(ProceedingJoinPoint jp, RateLimit rateLimit) throws Throwable { String key = jp.getSignature().toShortString(); counter.putIfAbsent(key, new AtomicInteger(0)); int count = counter.get(key).incrementAndGet(); if (count > rateLimit.limit()) { throw new RuntimeException("请求过多"); } return jp.proceed(); } }

⚠ 实际生产:
必须用 Redis + 令牌桶

什么时候用?
✔ 秒杀 ✔ 登录接口 ✔ 高频接口

四、AOP 使用优先级(你该怎么学)


第一阶段(你现在)

✔ 日志 AOP(必须) ✔ Around 用法

第二阶段(建议马上)

✔ TraceId ⭐⭐⭐⭐ ✔ 全局异常处理 ✔ 统一返回结构

第三阶段(进阶)

✔ 权限控制 ✔ 限流 ✔ 分布式链路追踪(SkyWalking)

五、AOP 使用误区(面试会问)


❌ 误区1:AOP 写业务逻辑

AOP 不处理业务,只处理“通用能力”

❌ 误区2:滥用 @Before

很多逻辑必须用 @Around

❌ 误区3:所有东西都用 AOP

能不用就不用,AOP是增强,不是主流程

六、总结


🔥 一句话总结:

AOP = 企业级“能力插件系统”

🔥 常见使用场景:

日志 → 必用 TraceId → 强烈推荐 权限控制 → 企业必备 限流 → 高并发场景

🔥 最关键认知:

你不是在学 AOP,而是在搭建“基础设施能力”

七、下一步建议

你可以继续做:

✔ AOP + TraceId + Logback 打通 ✔ 全局异常处理(@ControllerAdvice) ✔ 统一返回结构 Result

👉 这一套做完:

= 中级后端工程能力

http://www.jsqmd.com/news/704415/

相关文章:

  • 小米智能门锁临时密码管理:hass-xiaomi-miot数字组件实战指南
  • 告别误触困扰:键盘屏蔽器在专业办公环境中的应用指南
  • 重邮复试-网安笔试题目B卷
  • 【AI沙箱安全面试通关手册】:覆盖12家大厂高频题(含Kubernetes+Docker双重沙箱对比真题)
  • 告别玄学选型:用Python自动化测试英飞凌硅麦IM68A1308的动态范围与电压曲线
  • Dev Containers 安全性优化终极路线图:基于NIST SP 800-190A的7层防御体系,含OCI镜像扫描+运行时策略引擎集成实录
  • 【限时公开】某头部AIGC平台内部Docker Sandbox配置基线(v23.0.1+Ubuntu 22.04 LTS适配版)
  • Kindle Comic Converter:漫画爱好者的终极数字阅读指南
  • 2026年铝艺厂家推荐榜,铝艺大门/别墅庭院大门 - 品牌策略师
  • 如何用WindowResizer轻松突破Windows窗口尺寸限制:完整使用指南
  • C语言_题_逆序字符串
  • 从‘IndexError’到写出健壮代码:Python异常处理与防御性编程实战指南
  • C++内存分配器选型指南:除了GLibc的malloc,你还需要知道JeMalloc的这些“隐藏”特性
  • 如何彻底改变浏览器体验?NewTab-Redirect的7个创新用法
  • 解密Azure服务总线与逻辑应用的VNET集成
  • SUSFS4KSU-Module完整使用指南:掌握内核级Root隐藏的终极技巧
  • BiliBiliCCSubtitle技术解析:高效提取B站字幕的C++解决方案
  • 从ResNet到DenseNet:图解Element-wise Add和Concat如何塑造了现代CNN架构
  • 给嵌入式新手的RISC-V入门课:手把手拆解蜂鸟E203的流水线与模块(附Verilog代码片段)
  • Spring Boot项目里,Optional和@NotNull注解到底该怎么选?避坑指南
  • Spacebot:为团队协作设计的并发AI智能体框架架构解析与部署指南
  • 终极解放双手:MAA明日方舟自动化助手完整使用指南
  • Wegent:AI原生操作系统,构建可编排的智能体协作平台
  • 爱奇艺龚宇言论引舆论危机,长视频拥抱 AI 能否破局?
  • 从实验设计到机器学习:手把手教你用MATLAB拉丁超立方抽样生成高质量训练集
  • Python高级应用系列(十六)正则表达式高级技巧:re模块的深度应用
  • 基于视觉的AI智能体开发:Stagehand框架实现GUI自动化
  • 如何快速掌握DSGE建模:宏观经济研究的终极开源模型库指南
  • 4月25日滴滴顺风车安全治理开放日在沪举办,AI赋能出行安全,风险识别率达93.2%
  • Docker运行AI代码总被入侵?揭秘3层隔离失效链及5分钟应急熔断方案