什么是 Spring AOP

AOP(面向切面编程)是 Spring 两大核心之一,它是一种编程思想,是对 OOP 的一种补充。它通过横向抽取共性功能(如日志、事务),解决代码重复和耦合问题,提升代码复用性和可维护性。它的底层是通过动态代理实现的。

例子:记录 Controller 请求日志

如何给所有的 Controller 加日志?一个个加太麻烦、不好维护,且容易改错而导致出问题。

可以用 AOP 做统一的控制层日志记录。以 demo-log-aop 为例(为易于理解,省略了一些细节):

com.xkcoding.log.aop.controller包下有一个 Controller:

/**
 * 测试 Controller
 */
@Slf4j
@RestController
public class TestController {

    /**
     * 测试方法
     *
     * @param who 测试参数
     */
    @GetMapping("/test")
    public Dict test(String who) {
        return Dict.create().set(who);
    }
}

可以如下使用 AOP 切面记录请求日志:

/**
 * 使用 AOP 切面记录请求日志信息
 */
@Aspect
@Component
@Slf4j
public class AopLog {
    /**
     * 切入点
     */
    @Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))")
    public void log() {

    }

    /**
     * 环绕操作
     *
     * @param point 切入点
     * @return 原方法返回值
     * @throws Throwable 异常信息
     */
    @Around("log()")
    public Object aroundLog(ProceedingJoinPoint point) throws Throwable {
        // 调用方法
        Object result = point.proceed();
        // 构建日志对象
        final Log l = buildLog(point);
        // 打印日志
        log.info("Request Log Info : {}", JSONUtil.toJsonStr(l));
        // 返回原方法返回值
        return result;
    }
    
    /**
     * 构建日志对象
     */
    public Log buildLog(ProceedingJoinPoint point){
        // ...
    }
}

其中execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))是“切入点表达式”,可匹配“com.xkcoding.log.aop.controller 包下的所有以 Controller 结尾的类的所有 public 方法”——包括上面 TestController 中的 test 方法。

aroundLog 方法中写了具体的日志逻辑,在上面加@Around("log()")注解使其和log()绑定。

调用 TestController.test 之前,会发现切入点表达式匹配该方法,所以执行和该 Pointcut 绑定的 aroundLog 方法,aroundLog 中的point.proceed()完成了 TestController.test 的调用,调用 TestController.test 后,打印了相关的日志信息。

概念

  1. AOP:面向方面(切面)的程序设计(Aspect-Oriented Programming)。

  2. JoinPoint(连接点):在系统运行之前,AOP 的功能模块都需要织入到具体的功能模块中。要进行这种织入过程,我们需要知道在系统的哪些执行点上进行织入过程,这些将要在其之上进行织入操作的系统执行点就称之为 JoinPoint,最常见的 JoinPoint 就是方法调用。

  3. Pointcut(切点):用于指定一组 JoinPoint,代表要在这一组 JoinPoint 中织入我们的逻辑,它定义了相应 Advice 将要发生的地方。通常使用正则表达式来表示。对于做日志记录,Pointcut 就是表示“所有要加入日志记录的接口”的一个“表达式”。例如:“execution(* com.open.demo.service...(..))”。

  4. Advice(通知/增强):Advice 定义了将会织入到 JoinPoint 的具体逻辑,通过 @Before、@After、@Around 来区别在 JointPoint 之前、之后还是环绕执行的代码。

  5. Aspect(切面):Aspect 是对系统中的横切关注点逻辑进行模块化封装的 AOP 概念实体。类似于 Java 中的类声明,在 Aspect 中可以包含多个 Pointcut 以及相关的 Advice 定义。

  6. Weaving(织入):织入指的是将 Advice 连接到 Pointcut 指定的 JoinPoint 处的过程,也称为:将 Advice 织入到 Pointcut 指定的 JoinPoint 处。

参考:Spring AOP:基本概念

posted @ 2025-12-09 17:55  Higurashi-kagome  阅读(4)  评论(0)    收藏  举报