Spring Boot AOP 面向切面编程:从原理到实战,一篇就会
AOP 是 Spring 核心特性之一也是面试与日常开发高频使用的技能。它能帮我们无侵入地统一处理日志、权限、耗时统计、异常捕获等通用逻辑大幅减少重复代码、降低耦合。本文用最通俗的讲解 完整可运行案例带你彻底掌握 Spring Boot AOP。一、什么是 AOP为什么要用AOPAspect Oriented Programming 面向切面编程。核心思想把核心业务和通用非业务逻辑分离开。核心业务用户登录、下单、支付通用逻辑日志、鉴权、耗时统计、异常处理、事务不使用 AOP 的问题每个方法都写重复代码业务代码被污染修改麻烦牵一发动全身耦合度极高AOP 的好处无侵入不修改业务代码复用强一处编写多处生效易维护统一修改全局生效职责清晰业务归业务切面归切面二、AOP 核心术语一看就懂切面 Aspect要插入的通用功能日志、权限等切点 Pointcut在哪些方法上切入匹配规则通知 Advice在方法前/后/异常/环绕执行什么逻辑连接点 JoinPoint可以被切入的目标方法织入 Weaving把切面逻辑插入目标方法的过程目标对象 Target被代理的业务类三、AOP 五大通知类型Before方法执行前After方法执行后无论是否异常AfterReturning方法正常返回后AfterThrowing方法抛出异常后Around环绕通知最强大前后都能控制执行顺序Around 前 → Before → 方法执行 → AfterReturning → After → Around 后四、Spring Boot 快速使用 AOP1. 引入依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-aop/artifactId /dependency2. 编写业务类目标对象UserServiceService Slf4j public class UserService { public void printUserInfo(User user) { log.info(用户ID{}, user.getId()); log.info(用户名{}, user.getUsername()); log.info(昵称{}, user.getNickname()); } }ControllerRestController RequiredArgsConstructor public class UserController { private final UserService userService; PostMapping(/user) public String print(RequestBody User user) { userService.printUserInfo(user); return success; } }五、编写切面核心步骤Aspect Component Slf4j public class LogAspect { // 1. 定义切点匹配 UserService 所有方法 Pointcut(execution(* com.example.aop.service.UserService.*(..))) public void logPointcut() { } // 2. 前置通知 Before(logPointcut()) public void before() { log.warn([前置] 方法即将执行); } // 3. 后置通知 After(logPointcut()) public void after() { log.warn([后置] 方法已执行); } // 4. 返回通知 AfterReturning(logPointcut()) public void afterReturning() { log.warn([返回] 方法正常返回); } // 5. 异常通知 AfterThrowing(logPointcut()) public void afterThrowing() { log.error([异常] 方法报错了); } }切点表达式说明execution(* com.xxx.service.UserService.*(..)) * 任意返回值 .. 任意参数 * 任意方法名六、环绕通知 Around最常用环绕通知可以控制目标方法是否执行、修改参数、修改返回值、捕获异常。Around(logPointcut()) public Object around(ProceedingJoinPoint joinPoint) throws Throwable { log.warn([环绕前]); long start System.currentTimeMillis(); // 执行目标方法 Object result joinPoint.proceed(); long end System.currentTimeMillis(); log.warn([环绕后] 耗时{}ms, end - start); return result; }⚠️ 注意必须调用proceed()才会执行目标方法必须抛出异常或捕获否则业务异常会被吃掉七、在通知中获取方法参数可以在切面中拿到目标方法的入参常用于日志打印、参数校验。Before(logPointcut() args(user)) public void before(User user) { log.warn(参数{}, user); }多参数写法Before(logPointcut() args(user,id)) public void before(User user, Integer id) { ... }八、AOP 常见使用场景接口日志统一打印方法耗时统计全局权限校验全局异常捕获包装多数据源切换分布式锁、限流、幂等缓存自动处理操作日志审计九、避坑指南重要同类内部调用不生效this.method() 不走代理private 方法无法切入必须是 public异常不要在切面吞掉要抛出或包装环绕通知必须调用 proceed()避免切点表达式范围过大如*.*.*(..)导致性能问题十、总结Spring AOP 本质是动态代理帮我们无侵入增强方法。使用三步加 AOP 依赖写切点匹配哪些方法写通知前/后/环绕 增强逻辑AOP 让代码更干净、职责更清晰、维护更轻松是 Spring 开发必备技能。来自降重鸟技术团队请勿转载降重鸟地址https://jcn2.cn