AOP实践

星期四, 4月 30, 2026 | 1分钟阅读 | 更新于 星期四, 4月 30, 2026

@

接上一篇文章,了解了AOP的概念之后,这篇文章实践一下AOP在项目中的使用。

我直接在原来的learning-demo项目里面使用AOP记录controller接口的日志

修改依赖

<dependencies>
    <!-- Spring Boot AOP 核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
</dependencies>

修改好之后,用maven同步一下。

在项目已有的controller上实践AOP

获取所有用户接口

上图就是项目中已有的获取所有用户的接口。

下面就是日志记录类,使用AOP。

和controller接口的目录位置。

日志记录类目录结构

@Pointcut注解 execution表达式,表示要拦截哪个controller,当前的表达式的意思是controller包下面的任意类的任意一个方法,使用任意参数,都会被拦截。

Pointcut 切点表达式

有4类通知:

  1. 前置通知:在目标方法执行之前执行
  2. around通知:控制目标方法的执行时机
  3. 返回通知:在目标方法执行完成返回结果之后,执行。
  4. 后置通知:无论目标方法执行成功与否,是否抛异常,都会执行。

前置通知

    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        log.info("【前置通知】准备执行方法: {}, 传入的参数是: {}", methodName, Arrays.toString(args));
    }

Around通知

   @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        log.info("【环绕通知】目标方法执行前...");
        
        // 显式调用 proceed() 让目标方法去执行
        Object result = pjp.proceed(); 
        
        long endTime = System.currentTimeMillis();
        log.info("【环绕通知】目标方法执行后... 执行总耗时: {} 毫秒", (endTime - startTime));
        
        return result; // 必须把返回值 return 出去,否则前端拿不到数据
    }

返回通知

    @AfterReturning(value = "controllerPointcut()", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        log.info("【返回通知】方法 {} 执行完毕, 返回结果是: {}", methodName, result);
    }

后置通知

  @After("controllerPointcut()")
    public void doAfter(JoinPoint joinPoint) {
        log.info("【后置通知】方法 {} 最终结束", joinPoint.getSignature().getName());
    }
}

代码写入和测试

LoggingAspect 代码

代码写入到LoggingAspect.java。 运行一下。

趁着应用启动,先打开postman等着,奇怪的是,我用postman访问了一下接口,期待中的日志没有出现在终端上。我看看怎么回事。

好像是我aspect类的通知方法没有加注解的问题。我加上再试一下。

试了一下,果然如此。

为了Around通知明显一点,给接口加上500ms延迟。

测试一下:用获取全部用户的接口。 测试结果

可以,四个通知都成功打印到终端了。

四个通知的执行顺序可以看出来是

  1. Around,before
  2. Before
  3. AfterReturning
  4. After
  5. Around,after

四类日志记录的顺序

@Around (开始) -> 拦截请求,准备计时

@Before -> 进入方法前

执行Controller 里的代码

@AfterReturning -> 拿到 Controller 的返回值

@After -> 最终收尾

@Around (结束) -> 计算总耗时,放行结果

© 2026 My Blog

🌱 Powered by Hugo with theme Dream.