AOP是Spring框架核心特性之一,它不仅是一种编程思想更是实际项目中可以落地的技术实现技巧。通过自定义注解和AOP的组合使用,可以实现一些通用能力的抽象。比如很多接口都需要进行鉴权、日志记录或者执行时间统计等操作,但是如果在每个接口中都编写鉴权或者日志记录的代码那就很容易产生很多重复代码,在项目后期不好维护。针对这种场景 我们可以使用AOP同时结合自定义注解实现接口的切面编程,在需要进行通用逻辑处理的接口或者类中增加对应的注解即可。
计算指定某些接口的耗时情况,一般的做法是在每个接口中都加上计算接口耗时的逻辑,这样各个接口中就会有这样重复计算耗时的逻辑,重复代码就这样产生了。那么通过自定义注解和AOP的方式可以轻松地解决代码重复的问题。
我们采用自定义注解的方式,灵活使用AOP,步骤如下:
1.加入依赖,在项目的pom.xml加入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.4</version>
</dependency>
2.自定义注解
package com.study.anotation;
import java.lang.annotation.*;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CostTime {
}
3.定义切面实现类:
package com.study.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class CostTimeAspect {
@Pointcut(value = "@annotation(com.study.anotation.CostTime)")
public void costTime() {
}
@Around("costTime()")
public Object costTimeAround(ProceedingJoinPoint joinPoint) {
Object obj = null;
try {
long beginTime = System.currentTimeMillis();
obj = joinPoint.proceed();
//获取方法名称
String method = joinPoint.getSignature().getName();
//获取类名称
String className=joinPoint.getSignature().getDeclaringTypeName();
//计算耗时
long cost = System.currentTimeMillis() - beginTime;
log.info("类:[{}],方法:[{}] 接口耗时:[{}]", className,method, cost + "毫秒");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return obj;
}
}
4.优化前的代码:
@GetMapping("/list")
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {
long beginTime = System.currentTimeMillis();
List<OrderVO> orderVo = orderBizService.queryOrder(userId);
log.info("getOrderList耗时:" + System.currentTimeMillis() - beginTime + "毫秒");
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
@GetMapping("/item")
public ResponseResult<OrderVO> getOrderById(@RequestParam("id")String orderId) {
long beginTime = System.currentTimeMillis();
OrderVO orderVo = orderBizService.queryOrderById(orderId);
log.info("getOrderById耗时:" + System.currentTimeMillis() - beginTime + "毫秒");
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
5.优化后的代码:
@GetMapping("/list")
@CostTime
public ResponseResult<List<OrderVO>> getOrderList(@RequestParam("id")String userId) {
List<OrderVO> orderVo = orderBizService.queryOrder(userId);
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}
@GetMapping("/item")
@CostTime
public ResponseResult<OrderVO> getOrderList(@RequestParam("id")String orderId) {
OrderVO orderVo = orderBizService.queryOrderById(orderId);
return ResponseResultBuilder.buildSuccessResponese(orderVo);
}