Spring AOP/AspectJ 记录一个方法的执行时间但是如何给它传递参数? (Spring开机API)

Spring AOP/AspectJ logging the execution time of a method but how to pass arguments to it? (Spring boot API)

我在我的 Spring 启动 API 中使用 Spring AOP/AspectJ 在 Java 中做一个注释,就像 @TrackExecutionTime,我可以在任何方法上打耳光,并将该方法花费的总时间记录到 运行。这目前在我的 Spring 启动中有效。我的问题是,我的 API 每天被点击数千次,我想用这个执行时间记录一些其他独特的信息,所以我可以 track/trace 通过我的日志的每个请求。我可以使用的一些数据是通过 POST 请求正文从 JSON 发送的,但我看不到如何将这些参数传递到此注释的定义中 - 谁能帮忙?

我想从这个 Customer 对象传递一些参数(客户的名字、姓氏等),客户端将 POST 作为 JSON 到我的 API 到我的注释记录器:

@RestController
public class CustomersController implements CustomersApi {

    @Autowired
    private CustomerService customerService;

      return ResponseEntity.ok(offersService.fetchCustomer(Customer, clientId));
    }

我这样定义了具体的 class 和注解接口。这是我要传递客户对象的地方,以便我可以记录名字或姓氏:


@Aspect
@Component
@Slf4j
@ConditionalOnExpression("${aspect.enabled:true}")
public class ExecutionTimeAdvice {

    @Around("@annotation(com.mailshine.springboot.aop.aspectj.advise.TrackExecutionTime)")
    public Object executionTime(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object object = point.proceed();
        long endtime = System.currentTimeMillis();

        log.info("Class Name: "+ point.getSignature().getDeclaringTypeName() +". Method Name: "+ point.getSignature().getName() + ". Time taken for Execution is : " + (endtime-startTime) +"ms");
        return object;
    }
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackExecutionTime {
}

您可以尝试在注释中添加一个包含您想要的内容的字符串:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackExecutionTime {
    String getContent() default "";
}

在方法上使用它:

@TrackExecutionTime(getContent = "something")
private static void someMethod(...)

然后根据建议解析该内容:

@Around("@annotation(myAnnotation)") 
public Object executionTime(ProceedingJoinPoint point, TrackExecutionTime myAnnotation)throws Throwable {
    ...
    String content = myAnnotation.getContent();
}

这很容易做到;当我最初发布这个时我是一个笨蛋,但这里是任何想要做同样事情的人的答案:

当您创建使用 Spring AOP/AspectJ 定义注释的接口时,在您的具体 class 中,就像我上面列出的那样,它可以访问传递给您的方法的所有参数来自 ProceedingJoinPoint 对象。因此,您可以在此对象上调用 getArgs() 以获取在运行时传递给相关方法的所有参数。它将 return 一个 Object[] 因此您只需要进行一些条件检查以将其转换为您选择的类型并确保它不为空,这样您就不会在运行时遇到任何异常。如果客户 POST 访问您的 API 并且您想要跟踪方法的执行时间,但也许您有 hundreds/thousands 个请求并且需要专门跟踪 [=18],这将很有帮助=]确切地 哪些调用遵循哪些路径以及哪些因素可能会减慢您的 API 速度...因此从 requestBody 发布其他数据可能对您的日志有帮助...

例如我会假装我正在跟踪某种方法,该方法采用“学生”数据类型,该数据类型包含关于学生的一堆数据(姓名、dob、gpa 等...)。这样,如果我有不同的方法根据客户端 POST 到 API 的 requestBody 使用不同的 SQL 查询查询数据库,我可以记录它,以准确追踪哪个请求正在减慢我的 API 和它们在我的代码库中的流动以及它们正在调用的 SQL 查询。即

@Aspect
@Component
@Slf4j
@ConditionalOnExpression("${aspect.enabled:true}")
public class ExecutionTimeAdvice {

    @Around("@annotation(com.mailshine.springboot.aop.aspectj.advise.TrackExecutionTime)")
    public Object executionTime(ProceedingJoinPoint point) throws Throwable {
        MyCustomStudentType student; // Class to hold Student data
        String studentName = "";
        Object[] argsArray = point.getArgs();
        
        if (argsArray.length > 0 && argsArray[0] instanceof MyCustomStudentType) {
             student = (MyCustomStudentType) argsArray[0];
             studentName = student.getName();
        }

        long startTime = System.currentTimeMillis();
        Object object = point.proceed();
        long endtime = System.currentTimeMillis();

        // add the student name to your logs or any info you want to add with your
        // execution time of your method, to make tracking your logs easier
        log.info("Class Name: "+ point.getSignature().getDeclaringTypeName() +". Method Name: "+ point.getSignature().getName() + ". Time taken for Execution is : " + (endtime-startTime) +"ms" + ", for student name: " + studentName);

        return object;
    }
}