
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод 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 в 2026-2027 годах? Или это полная лажа?".

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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.