侧边栏壁纸
博主头像
八月寻英 博主等级

大道至简,知易行难

  • 累计撰写 38 篇文章
  • 累计创建 14 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

AOP封装一个记录耗时的注解

smy
smy
2025-04-23 / 0 评论 / 0 点赞 / 21 阅读 / 0 字 / 正在检测是否收录...

代码实现

  • 那现在我们来从头编写一个TakeTimeAspect类,该类通过AOP的方式来监控方法的执行时间,并且记录相关的日志信息。首先导入AOP的依赖

  • 代码实现

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class TakeTimeAspect {

    // ThreadLocal变量用于存储开始时间和结束时间
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    ThreadLocal<Long> endTime = new ThreadLocal<>();

    // 定义一个切入点,匹配带有@TakeTimeLog注解的方法
    @Pointcut("@annotation(com.aimc.paperreduction.common.annotation.TakeTimeLog)")
    public void TakeTime() {}

    // 前置增强方法,在方法执行前记录开始时间
    @Before("TakeTime()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 获得注解
        TakeTimeLog timeLog = getAnnotationLog(joinPoint);
        if (timeLog == null) {
            return;
        }

        startTime.set(System.currentTimeMillis());
    }

    // 返回后增强方法,在方法执行后记录结束时间和执行时间,并记录日志
    @AfterReturning(returning = "ret", pointcut = "TakeTime()")
    public void doAfterReturning(JoinPoint joinPoint, Object ret) {
        Map<String, Object> resultMap = new HashMap<>();
        String[] names = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        if (names.length > 0) {
            for (int i = 0; i < names.length; i++) {
                if (!(joinPoint.getArgs()[i] instanceof HttpServletRequest)) {
                    resultMap.put(names[i], joinPoint.getArgs()[i]);
                }
            }
        }
        // 处理完请求后,返回内容
        log.info("Return:" + JSON.toJSONString(ret));
        endTime.set(System.currentTimeMillis());
        log.info("Execution Time:" + (endTime.get() - startTime.get()));
    }

    // 用于获取方法上的注解
    private TakeTimeLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(TakeTimeLog.class);
        }
        return null;
    }
}
  • ThreadLocal<Long> startTimeThreadLocal<Long> endTime:这两个是ThreadLocal变量,用于存储方法执行的开始时间和结束时间,用于计算方法的执行时间。ThreadLocal允许存储每个线程特定的数据,确保线程安全性。

  • 切点表达式:@Pointcut("@annotation(com.aimc.paperreduction.common.annotation.TakeTimeLog)"),匹配带有@TakeTimeLog注解的方法。

  • 增强方法

    1. @Before("TakeTime()"):在匹配TakeTime切入点的方法之前执行。它捕获方法执行开始的时间,当然这里也可以获取更多的信息,例如方法参数之类的信息都可以拿到,这里我们根据自身项目的需求来编写。

    2. @AfterReturning(returning = "ret", pointcut = "TakeTime()"):这是一个返回后增强方法。它捕获方法的结束时间,记录返回值,并计算并记录执行时间。

  • getAnnotationLog:这是一个私有方法,用于从目标方法中获取TakeTimeLog注解(如果存在)。

使用方式

  • 我们在需要记录耗时的方法上加上此注解即可

@TakeTimeLog
public Wrapper<UploadPaperDTO> uploadDoc(MultipartFile file) throws IOException {
    /**
     *  你的代码逻辑
     */
}

0
  • 0

评论区