一、前言在学习 Spring AOP 时很多人最先接触的是Around(execution(* com.xxx.service..*(..)))但随着项目复杂度提升你会开始看到另一种写法Around(annotation(operationLog))这时候就会产生一个非常典型的疑问❗ execution 和 annotation 到底有什么区别是不是重复了如果你只是停留在“语法层”你会觉得只是两种写法而已但如果从工程角度看这其实是一个非常关键的设计问题。二、核心结论先给答案先记住这一句execution 按“代码位置”拦截全局 annotation 按“标记”拦截精确企业项目中真正的用法是execution annotation 组合使用三、execution按“代码位置”拦截1. 基本写法Around(execution(* com.xxx.modules..controller..*(..)))2. 含义拆解execution( * 任意返回值 com.xxx.modules 指定包 .. 子包 controller.. controller 层 *.* 所有类的所有方法 (..) 任意参数 ) 本质按“包路径”拦截3. 适合场景✔ 请求日志所有接口都要记录 ✔ 统一监控 ✔ 全局增强4. 举例Around(execution(* com.xxx.modules..controller..*(..))) public Object log(ProceedingJoinPoint joinPoint) { // 所有接口都会进来 }四、annotation按“标记”拦截1. 基本写法Around(annotation(operationLog))2. 含义只拦截“带某个注解的方法”3. 使用方式第一步定义注解Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface OperationLog { String module() default ; String action() default ; }第二步标记方法OperationLog(module 用户模块, action 创建用户) PostMapping(/create) public ResultVoid createUser() { return Result.success(); }第三步AOP 拦截Around(annotation(operationLog)) public Object operationLog(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable { log.info(操作日志module{}, action{}, operationLog.module(), operationLog.action()); return joinPoint.proceed(); } 本质按“标记”拦截五、为什么 execution 不够用关键假设有一个 Controller20 个接口但真正需要记录“操作日志”的只有创建用户 删除用户 支付 退款❌ 如果用 executionAround(execution(* com.xxx.modules.user.controller..*(..)))结果20 个接口全部被拦截 ❌✅ 正确做法annotationOperationLog(...) 只给关键接口打标记精准控制六、企业项目的真实用法重点实际项目不会只用一种而是组合1️⃣ 请求日志全局Around(execution(* com.xxx.modules..controller..*(..))) 所有接口都记录日志2️⃣ 操作日志关键接口Around(annotation(operationLog)) 只记录关键操作3️⃣ 权限控制Around(annotation(checkPermission))4️⃣ 限流Around(annotation(rateLimit)) 总结execution → 全局能力 annotation → 精细控制七、组合写法面试加分你甚至可以组合Around(execution(* com.xxx.modules..controller..*(..)) annotation(operationLog))含义只拦 controller 层 且带注解的方法八、设计思路总结最重要execution 扫一片全拦 annotation 点名精确 企业项目 execution annotation 组合九、常见误区❌ 误区1只会 execution所有接口都被拦 无法精细控制❌ 误区2只用 annotation每个接口都要加注解 维护成本高❌ 误区3不区分场景日志、权限、限流全部混在一起十、面试怎么说直接可用如果面试官问你项目里 AOP 怎么用的可以这样回答我在项目中区分了两种切点方式。execution 主要用于全局能力比如请求日志我会在 controller 层统一拦截所有接口。annotation 主要用于精细控制比如操作日志、权限校验、限流我会通过自定义注解标记关键接口然后通过 AOP 进行拦截。在实际项目中我是将 execution 和 annotation 组合使用从而实现全局能力和精细控制的统一。十一、总结这篇文章最核心的不是语法而是设计思路AOP 的价值不是“能拦截”而是“如何优雅地控制拦截范围”最终你要做到的是全局能力 → execution 关键能力 → annotation 工程落地 → 两者组合十二、延伸如果你已经看完前几篇Spring AOP 从原理到实战结合事务彻底搞懂Spring AOP 进阶实战从日志到权限/链路追踪/限流真正企业用法Spring Boot 工程化进阶统一返回 全局异常 AOP 通用工具包AOP 原理 AOP 工程化 统一返回 异常处理那么这一篇补齐的是AOP 切点设计能力这一步非常关键因为从“会用 AOP” 到“会设计 AOP”这就是中级工程师的分水岭。