#spring-aop
#spring-aop
Вопрос:
У меня есть класс GlobalExceptionHandler, который содержит несколько методов, аннотированных с помощью @ExceptionHandler.
@ExceptionHandler({ AccessDeniedException.class })
public final ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
У меня есть AOP, который, как предполагается, запускается после того, как обработчик исключений вернет ответ.
@AfterReturning(value="@annotation(exceptionHandler)",returning="response")
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
Но @AfterReturning не запускается после того, как обработчик вернет допустимый ответ.
Пробовал использовать полное имя, но не работает
@AfterReturning(value = "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)", returning = "response"){
public void afterReturningAdvice(JoinPoint joinPoint, Object response) {
//do something
}
Комментарии:
1. Вы должны использовать полное имя для аннотации,
@AfterReturning(value = "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)", returning = "response")
.2. пробовал, но все еще не работает
3. Пожалуйста, также укажите класс, содержащий
afterReturningAdvice
метод.4. @KiranKumar, я скопировал код, которым поделился с вашим вопросом, и совет сработал в моем тестовом проекте. Пожалуйста, подтвердите, автоматически ли определяется класс aspect контейнером Spring посредством сканирования компонентов. Если все это верно, пожалуйста, поделитесь всем контроллером, рекомендациями по контроллеру, аспектным кодом или минимальным воспроизводимым примером
5. @R.G, не хотели бы вы написать ответ, объясняющий, почему Spring AOP не работает с конечными целевыми методами, чтобы OP мог принять это и закрыть вопрос? Я не хочу красть вашу репутацию. Киран: Это плохая идея изменять код после его копирования. Скорее переключитесь на новую ветку Git, измените код (например, переименовав имена конфиденциальных пакетов и классов, удалив ненужный код для воспроизведения проблемы), проверьте, по-прежнему ли он воспроизводит проблему таким же образом, сделайте фиксацию (чтобы позже вы могли снова переключиться на эту ветку и протестировать ответ), а затем опубликуйте здесь. Наша работа заключается в деталях.
Ответ №1:
Пожалуйста, ознакомьтесь с документацией, чтобы понять механизмы прокси в Spring Framework.
Предполагая, что ExceptionHandler
написанный код имел следующий формат
@ControllerAdvice
public class TestControllerAdvice {
@ExceptionHandler({ AccessDeniedException.class })
final public ResponseEntity<Object> handleAccessDeniedException(
Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
"Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);
}
}
ключевыми моментами из документации, относящейся к вопросу, являются
-
Spring AOP использует либо динамические прокси JDK, либо CGLIB для создания прокси для данного целевого объекта.
-
Если целевой объект, который должен быть проксирован, реализует хотя бы один интерфейс, используется динамический прокси-сервер JDK. Все интерфейсы, реализованные целевым типом, проксируются. Если целевой объект не реализует никаких интерфейсов, создается прокси CGLIB.
-
В CGLIB нельзя рекомендовать конечные методы, поскольку они не могут быть переопределены в подклассах, сгенерированных во время выполнения.
- OP определил проблему на основе комментариев и подсказок, этот ответ предназначен для любых будущих ссылок.