Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше времени, чем нужно? Что если вас попросили создать глобальное решение в вашем Spring Boot API? Если да, то эта статья может быть идеальной для вас.
В предыдущей статье мы создали аннотацию для фиксации времени выполнения метода. Теперь давайте создадим пару параметров, которые могут быть отправлены вместе с аннотацией в качестве атрибутов для дальнейшей обработки. Как вы можете видеть, мы создали две переменные
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ExecutionTimeLogger { int maxThresholdTime() default 0; ExecutionTimeUnit executionTimeUnit() default ExecutionTimeUnit.SECONDS; enum ExecutionTimeUnit { MILLISECONDS, SECONDS, MINUTES } }
Давайте теперь проверим, как эти дополнительные переменные становятся полезными в вашем аспекте. Если у вас нет базового понимания того, как работают @Aspect и @Around, пожалуйста, просмотрите начальную статью . Как вы можете видеть в приведенном ниже коде, теперь мы будем передавать класс Annotation в качестве параметра в нашем методе AOP.
Поскольку аннотация доступна вместе со своим параметром внутри метода Spring AOP, мы можем получить эти переменные из объекта аннотации и обработать их дальше так, как нам нужно. В нашем примере мы используем оба параметра для создания предупреждения в файле журнала, однако вы можете сделать все, что захотите (например, выдать предупреждение по электронной почте, записать его в базу данных и т.д.) в соответствии с вашим сценарием использования.
В приведенном ниже коде мы проверяем, установлен ли ExecutionTimeUnit пользователем, если нет, то по умолчанию считается Second TimeUnit. Время выполнения метода вычисляется в заданном TimeUnit. После этого код проверяет, что если время выполнения превышает maxThresholdTime, то генерируется предупреждение в журналах.
@Aspect @Component public class ExecutionTimeLoggerAspect { static final Logger logger = LoggerFactory.getLogger(ExecutionTimeLoggerAspect.class); @Around("@annotation(executionTimeLogger)") public Object executionTimeLogger(ProceedingJoinPoint joinPoint, ExecutionTimeLogger executionTimeLogger) { try { long startTime = System.currentTimeMillis(); Object proceed = joinPoint.proceed(); long executionTime = (System.currentTimeMillis() - startTime); ExecutionTimeUnit executionTimeUnit = executionTimeLogger.executionTimeUnit(); switch (executionTimeUnit) { case MILLISECONDS: break; case MINUTES: executionTime = executionTime / 60000; break; case SECONDS: default: executionTime = executionTime / 1000; break; } int maxThresholdTime = executionTimeLogger.maxThresholdTime(); if (maxThresholdTime > 0 && executionTime > maxThresholdTime) { logger.warn( "{} method was executed in {} {} which was higher than expected Max Threshold Time of {} {}", joinPoint.getSignature(), executionTime, executionTimeUnit, maxThresholdTime, executionTimeUnit); // Trigger an Email // Log it in Database } else { logger.info("{} method was executed in {} {}", joinPoint.getSignature(), executionTime, executionTimeUnit); } return proceed; } catch (Throwable e) { logger.error("There was an error while calculating method execution time for {}", joinPoint.getSignature(), e); return null; } } }
Давайте теперь проверим, как мы можем использовать эту аннотацию в различных комбинациях, чтобы получить преимущества концепций Spring AOP.
public class CustomizedExecutionLogging { //Log method execution time @ExecutionTimeLogger public void aspectMethodOne() throws InterruptedException { Thread.sleep(2000); } //Log warning if method takes more than 2 seconds @ExecutionTimeLogger(maxThresholdTime = 2) public void aspectMethodTwo() throws InterruptedException { Thread.sleep(3000); } //Log warning if method takes more than 50 milliseconds @ExecutionTimeLogger(maxThresholdTime = 50, executionTimeUnit = ExecutionTimeUnit.MILLISECONDS) public void aspectMethodThree() throws InterruptedException { Thread.sleep(100); } }
#OUTPUT
C.n.a.e.ExecutionTimeLoggerAspect : void com.niket.agrawal.executionTimeLogger.MethodExecutions.aspectMethodOne() метод был выполнен за 2 СЕКУНДЫ
C.n.a.e.ExecutionTimeLoggerAspect : void com.niket.agrawal.executionTimeLogger.MethodExecutions.aspectMethodTwo() метод был выполнен за 3 СЕКУНДЫ, что выше ожидаемого максимального порогового времени в 2 СЕКУНДЫ
C.n.a.e.ExecutionTimeLoggerAspect : void com.niket.agrawal.executionTimeLogger.MethodExecutions.aspectMethodThree() метод был выполнен за 109 МИЛЛИСЕКУНД, что выше ожидаемого максимального порогового времени в 50 МИЛЛИСЕКУНД.
Пример кода можно посмотреть на GitHub: https://github.com/niket17590/executionTimeLogger
Как вы можете видеть, в мире Spring Boot & AOP существуют бесконечные возможности, а также он становится все лучше и лучше, когда концепции становятся ясными.
Надеюсь, эта статья поможет вам улучшить свои знания о концепциях Spring Boot & Spring AOP.
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
14.08.2023 14:49
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.