Spring Boot 整合 AOP 实现接口切面日志

发布时间:2024年01月02日

Spring Boot 整合 AOP 实现接口切面日志

什么是 AOP?

AOP(Aspect-Oriented Programming)是一种编程范式,它允许开发人员将横切关注点(如日志记录、性能统计、安全性等)从主要业务逻辑中分离出来,以便更好地模块化和管理这些关注点。

AOP通过定义切面(Aspect)来实现这一目标,切面包含了通知(Advice)和切点(Pointcut),通知定义了在何时、何地执行横切逻辑,而切点定义了在何处执行横切逻辑。通过将切面与应用程序的其他部分进行连接,AOP可以实现横切关注点的统一管理和重用。

AOP通常用于解决跨越多个模块的横切关注点,例如日志记录、事务管理、安全性等。

在这里插入图片描述

我们可以简单的把 AOP 理解为贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。

AOP相关术语

切面(Aspect): 对横切关注点进行封装的类,每个关注点体现为一个通知方法;通常使用 @Aspect 注解来定义切面。

通知(Advice): 切面必须要完成的各个具体工作,比如我们的日志切面需要记录接口调用前后的时长,就需要在调用接口前后记录时间,再取差值。通知的方式有五种:

  • @Before:通知方法会在目标方法调用之前执行
  • @After:通知方法会在目标方法调用后执行
  • @AfterReturning:通知方法会在目标方法返回后执行
  • @AfterThrowing:通知方法会在目标方法抛出异常后执行
  • @Around:把整个目标方法包裹起来,在被调用前和调用之后分别执行通知方法

连接点(JoinPoint): 通知应用的时机,比如接口方法被调用时就是日志切面的连接点。

切点(Pointcut): 通知功能被应用的范围,比如本篇日志切面的应用范围是所有 controller 的接口。通常使用 @Pointcut 注解来定义切点表达式。

代码实现 AOP 记录接口访问日志

整合 POM 依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

定义 ApiLog 注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiLog {

}

实现 ApiLogAspect 切面

@Slf4j
@Aspect
@Component
public class ApiLogAspect {

    @Pointcut("@annotation(com.itwenke.springbootdemo.aop.aspect.ApiLog) || @within(com.itwenke.springbootdemo.aop.aspect.ApiLog)")
    public void getLogAnnotation() {
    }

    @Around("getLogAnnotation()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object ans = joinPoint.proceed();
            return ans;
        } finally {
            log.info("执行耗时: {}#{} = {}ms",
                    joinPoint.getSignature().getDeclaringType().getSimpleName(),
                    joinPoint.getSignature().getName(),
                    System.currentTimeMillis() - start);
        }
    }
}

编写 Controller 测试接口

@RequestMapping(path = "api/test")
@RestController
public class TestController {

    @RequestMapping(path = "hi")
    @ApiLog()
    public String hi() {
        return "hi";
    }

    @RequestMapping(path = "select")
    @ApiLog()
    public String select() throws InterruptedException {
        Thread.sleep(5000);
        return "select";
    }
}

接口测试

http://localhost:8080/api/test/hi
http://localhost:8080/api/test/select

2024-01-02 15:32:33.567  INFO 4548 --- [nio-8080-exec-2] c.i.s.aop.aspect.ApiLogAspect            : 执行耗时: TestController#hi = 0ms
2024-01-02 15:32:42.417  INFO 4548 --- [nio-8080-exec-5] c.i.s.aop.aspect.ApiLogAspect            : 执行耗时: TestController#select = 5005ms
文章来源:https://blog.csdn.net/qq_45607784/article/details/135341463
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。