使用AOP的形式,创建一个切面
    image.png

    1. package com.lv.aspect;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.aspectj.lang.ProceedingJoinPoint;
    4. import org.aspectj.lang.annotation.Around;
    5. import org.aspectj.lang.annotation.Aspect;
    6. import org.springframework.stereotype.Component;
    7. import java.time.Duration;
    8. import java.time.LocalDateTime;
    9. /**
    10. * @author
    11. * Create Date:2021/5/23
    12. */
    13. @Slf4j
    14. @Aspect//表示是一个切面
    15. @Component//是一个组件
    16. public class ServiceLogAspect {
    17. /**
    18. * AOP通知:
    19. * 1、前置通知:在方法调用之前执行
    20. * 2、后置通知:在方法调用之后执行
    21. * 3、环绕通知:在方法调用之前和之后,都分别可以执行的通知
    22. * 4、异常通知:如果在方法调用过程中发生异常,则通知
    23. * 5、最终通知:在方法调用之后执行
    24. * <p>
    25. * 切面表达式:
    26. * execution:代表所有要执行的表达式主体
    27. * 第一处: * 代表方法返回类型, * 代表所有类型
    28. * 第二处: 包名代表aop监控的类所在的包
    29. * 第三处: .. 代表该包以及其子包下的所有类方法
    30. * 第四处: * 代表类名,* 代表所有类
    31. * 第五处: *(..) * 代表类中的方法名 (..)方法中任何参数
    32. */
    33. @Around("execution(* com.lv.serviceImpl..*.*(..))")
    34. public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
    35. // 获取调用方法后的类名与方法名
    36. log.info("======= 开始执行 {}.{} =======",
    37. // 目标是哪个类
    38. joinPoint.getTarget().getClass(),
    39. // 签名
    40. joinPoint.getSignature().getName());
    41. // 记录开始时间
    42. LocalDateTime begin = LocalDateTime.now();
    43. // 执行目标 Service
    44. Object result = joinPoint.proceed();
    45. // 记录结束时间
    46. LocalDateTime end = LocalDateTime.now();
    47. // 获取时间差
    48. Duration duration = Duration.between(begin, end);
    49. long takeTime = duration.toMillis();
    50. if (takeTime > 3000) {
    51. log.error("======= 执行结束,耗时:{} 毫秒 =======", takeTime);
    52. } else {
    53. log.info("======= 执行结束,耗时:{} 毫秒 =======", takeTime);
    54. }
    55. return result;
    56. }
    57. }