一、什么是AOP?

全称:Aspect Oriented Programming(面向切面编程 / 面向方面编程)

定义:在不改变原始业务逻辑的前提下,将一些公共行为(如日志、权限校验、事务控制等)从业务代码中抽取出来统一管理

场景:案例中部分业务方法运行较慢,定位执行耗时较长的接口,此时需要统计每一个业务方法的执行耗时。


✅ AOP 优势
优势 说明
减少重复代码 公共逻辑抽出,不需重复写
代码无侵入 原业务逻辑不需要修改
提高开发效率 共性功能一次配置,全局生效
易于维护 修改公共逻辑时,只需改一处即可


二、AOP核心概念

✅概念
名称 含义说明
JoinPoint 连接点:可以被 AOP 拦截的方法或执行点(如所有方法)
PointCut 切入点:实际要拦截的方法的定义规则(如 service.*)
Advice 通知:定义要执行的横切逻辑(如日志、权限)
Aspect 切面:通知 + 切入点的组合体
Target 目标对象:被增强的原始业务类


✅引入依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

✅编写切面类
@Slf4j
@Aspect
@Component
public class TimeAspect {

    @Around("execution(* com.xxx.service.impl.*.*(..))")
    public Object recordExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();

        Object result = pjp.proceed();  // 原始方法执行

        long end = System.currentTimeMillis();
        log.info("执行方法:{},耗时:{}ms", pjp.getSignature(), end - start);
        return result;
    }
}


三、通知类型详解

✅通知类型
通知注解 说明
@Around 环绕通知,目标方法前后都能执行 ✅ 最常用
@Before 前置通知,在目标方法执行前调用
@After 后置通知,无论是否异常都会执行
@AfterReturning 返回后通知,方法正常返回后执行(异常不会执行
@AfterThrowing 异常通知,目标方法抛出异常时执行

✅ @PointCut 抽取公共切入点表达式
@Pointcut("execution(* com.xxx.service.impl.*.*(..))")
private void serviceMethods() {}

@Around("serviceMethods()")
public Object around(ProceedingJoinPoint jp) { ... }

✅ 通知顺序

不同切面类中,默认按照切面类的类名字母排序:

  • 目标方法前的通知方法:字母排名靠前的先执行

  • 目标方法后的通知方法:字母排名靠前的后执行

@Order(数字)加在切面类上来控制顺序

  • 目标方法前的通知方法:数字小的先执行
  • 目标方法后的通知方法:数字小的后执行


四、切入点表达式详解

execution 表达式语法
execution([修饰符] 返回值类型 包名.类名.方法名(参数) throws 异常)

✅ 通配符说明
通配符 含义
* 匹配任意单个项(如返回值、类名等)
匹配任意层级包名 / 参数列表

✅ @annotation 表达式(通过注解匹配)
  • 适用于无法通过方法签名表达的切面需求(如指定加了某个注解的方法)
@Around("@annotation(com.itheima.anno.Log)")


五、连接点

对于@Around通知,获取连接点信息只能使用 ProceedingJoinPoint 

对于其它四种通知,获取连接点信息只能使用 JoinPoint ,它是 ProceedingJoinPoint 的父类型

方法         作用
getTarget() 获取目标对象
getTarget().getClass().getName(); 获取目标类
getSignature().getName(); 获取目标方法
getArgs(); 获取目标方法参数


 六、ThreadLocal 用于传递登录用户信息

✅ 问题:如何从 JWT 中解析出的员工 ID 传给 AOP 程序?
✅ ThreadLocal 原理
  • 是“线程内的全局变量”
  • 每个线程有自己独立的变量副本,线程安全
✅ 用法示例
// 设置
ThreadLocalUtils.set(currentUserId);

// 获取
Long id = ThreadLocalUtils.get();

// 清除
ThreadLocalUtils.remove();
✅ 应用流程
  1. 在 TokenFilter 中解析 JWT,得到登录员工 ID
  2. 将 ID 存入 ThreadLocal
  3. 在 AOP 或 Controller 中读取 ThreadLocal 获取登录用户信息
  4. 用完清除,避免内存泄漏


 ✅ 总结表

模块 核心内容与关键理解点
AOP 概念 统一处理共性问题的技术(如日志、安全、事务)
核心术语 JoinPoint、PointCut、Advice、Aspect、Target
通知类型 @Before、@After、@Around、@AfterReturning、@AfterThrowing
表达式写法 execution、@annotation,支持通配符 * 和 …
实战日志案例 使用环绕通知 + ThreadLocal + JWT 实现用户行为记录
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐