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