Spring AOP /AspectJ регистрирует время выполнения метода, но как передать ему аргументы? (API весенней загрузки)

#java #spring #aop #aspectj

#java #весна #aop #aspectj

Вопрос:

Я использую Spring AOP / AspectJ в моем Spring Boot API, чтобы создать аннотацию на Java, подобную @TrackExecutionTime той, которую я могу использовать для любого метода, и она регистрирует общее время, необходимое для запуска метода. В настоящее время это работает в моей весенней загрузке. Моя проблема в том, что мой API получает доступ тысячи раз в день, и я хочу регистрировать какую-то другую уникальную информацию с этим временем выполнения, чтобы я мог отслеживать / отслеживать каждый запрос в своих журналах. Некоторые данные, которые я могу использовать, отправляются с телом запроса POST из JSON, но я не вижу, как передать эти аргументы в определение этой аннотации — кто-нибудь может помочь?

Я хочу передать некоторые аргументы (имя клиента, фамилия и т. Д.) Из этого объекта Customer, который является RequestBody, который клиент отправит в виде JSON в мой API в мой регистратор аннотаций:

 @RestController
public class CustomersController implements CustomersApi {

    @Autowired
    private CustomerService customerService;

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

Я определил конкретный класс и интерфейс для аннотации следующим образом. Именно здесь я хочу передать объект Customer, чтобы я мог зарегистрировать имя или фамилию:

 
@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 {
}
 

Ответ №1:

Вы можете попробовать добавить строку с нужным содержимым в аннотацию:

 @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();
}
 

Ответ №2:

Это очень легко сделать; Я был тупицей, когда впервые опубликовал это, но вот ответ для тех, кто хочет сделать то же самое:

Когда вы создаете свой интерфейс, который определяет вашу аннотацию, используя Spring AOP / AspectJ, в вашем конкретном классе, как я перечислил выше, он имеет доступ ко всем аргументам, переданным вашему методу из объекта ProceedingJoinPoint . Таким образом, вы можете вызвать getArgs() этот объект, чтобы получить все аргументы, переданные рассматриваемому методу при его запуске. Он вернет Object[], поэтому вам просто нужно будет выполнить несколько условных проверок, чтобы привести его к выбранному вами типу и убедиться, что он не пустой, чтобы вы не получили никаких исключений во время выполнения. Это полезно, если клиенты отправляют сообщения в ваш API, и вы хотите отслеживать время выполнения методов, но, возможно, у вас есть сотни / тысячи запросов, и вам нужно конкретно отследить, какие вызовы следуют по каким путям и что может замедлять работу вашего API… поэтому публикация дополнительных данных из RequestBody может быть полезной в ваших журналах…

например, я притворюсь, что отслеживаю какой-то метод, который принимает тип данных «Student», Который содержит кучу данных о студенте (имя, dob, средний балл и т. Д.). Таким образом, если у меня есть разные методы, которые запрашивают базу данных с помощью разных SQL-запросов на основе RequestBody, которые клиент отправляет в API, я могу зарегистрировать это, чтобы точно отследить, какие запросы замедляют работу моего 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 amp;amp; 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;
    }
}