Виды советов (Advice) в Spring AOP
В Spring AOP «совет» (advice) — это фрагмент дополнительного кода, который выполняется до, после или вместо вызова основного метода.
Существует пять основных типов:
• @Before — выполняется перед методом.
• @After — выполняется после метода, независимо от результата.
• @AfterReturning — только если метод завершился успешно.
• @AfterThrowing — при возникновении исключения.
• @Around — оборачивает метод целиком, позволяя контролировать его выполнение.
Подробное объяснение
Spring AOP позволяет внедрять дополнительное поведение в определенные участки программы, не меняя основной код.
Такое поведение описывается в методах-советах, которые помечаются аннотациями. Ниже приведены основные варианты и примеры их применения.
1. @Before
Выполняется перед вызовом целевого метода.
Обычно используется для логирования, валидации входных данных или проверки прав доступа.
@Before("execution(* com.example.service.*.*(..))")
public void beforeCall() {
System.out.println("Подготовка перед вызовом метода");
}
Когда любой метод из пакета service будет вызван, этот совет выполнится раньше основной логики.
2. @After
Срабатывает после метода в любом случае — и при нормальном завершении, и при исключении.
Применяется для освобождения ресурсов или записи в аудит-журнал.
@After("execution(* com.example.service.*.*(..))")
public void afterCall() {
System.out.println("Метод завершен (успешно или с ошибкой)");
}
3. @AfterReturning
Срабатывает только если метод завершился без исключений.
Позволяет получить возвращаемое значение и проанализировать результат.
@AfterReturning(
pointcut = "execution(* com.example.service.UserService.get*(..))",
returning = "result")
public void afterSuccess(Object result) {
System.out.println("Метод вернул результат: " + result);
}
Аргумент returning связывает параметр метода-совета с результатом вызова основного метода.
4. @AfterThrowing
Вызывается, если метод завершился с ошибкой.
Полезно для централизованного логирования исключений.
@AfterThrowing(
pointcut = "execution(* com.example.service.*.*(..))",
throwing = "ex")
public void afterError(Exception ex) {
System.out.println("Произошла ошибка: " + ex.getMessage());
}
Такой подход позволяет собирать информацию о сбоях без добавления try-catch в каждый сервисный метод.
5. @Around
Самый гибкий тип. Он полностью контролирует процесс вызова: можно выполнить действия до и после, изменить аргументы или даже отменить сам вызов.
Реализуется через интерфейс ProceedingJoinPoint.
@Around("execution(* com.example.service.*.*(..))")
public Object measureTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // вызывает оригинальный метод
long duration = System.currentTimeMillis() - start;
System.out.println("Метод " + joinPoint.getSignature() +
" занял " + duration + " мс");
return result;
}
Метод proceed() инициирует выполнение основного кода, а все остальное — логика аспекта.
Таким образом, @Around используется для измерения времени, управления транзакциями или реализации собственных фильтров.
Вывод:
Пять типов advice позволяют гибко вмешиваться в жизненный цикл выполнения методов.
Используя их в комбинации, можно отделить повторяющуюся инфраструктурную функциональность (логирование, аудит, контроль доступа) от деловой логики и сделать код чище и поддерживаемее.
