У меня есть приложение Spring 5.0.4 с файлом конфигурации сервлета Dispatcher как spring-web-servlet.xml
(spring-web - это имя сервлета Dispatcher).Чтобы включить AOP в приложении, я сделал запись <aop:aspectj-autoproxy />
в spring-web-servlet.xml
после включения пространства имен для aop.
В pom.xml
есть следующие записи:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
Для использованияАОП, я создал ниже класс Aspect:
@Aspect
@Component
public class MyAspect {
@Before("getApiPointcut()")
public void logRequest(JoinPoint joinPoint) {
//some logic here
}
@AfterReturning(value = "getApiPointcut()", returning = "returnValue")
public void logResponse(Object returnValue) {
//some logic here
}
@Pointcut("within(com.test.service.controller.*) " +
" || within(com.test.service.api.GenericService)" +
" || within(com.test.service.api.UserService)")
public void getApiPointcut() {
}
}
Этот класс имеет два метода: logRequest () и logResponse ().Каждый вызов API сначала проходит через logRequest (), и перед возвратом ответа вызывается logResponse ().
Для начальных нескольких запросов (5-6) AOP работает нормально, и я получаю поток в классе MyAspectдля обоих методов.
Но после этого, если я нажму какой-либо API, поток проходит через logRequest (), затем класс API, а затем зависает.Класс API вызывает класс обслуживания.Но поток никогда не достигает класса обслуживания и, следовательно, никогда не входит в logResponse (), и сервер ничего не возвращает клиенту.Я проверил журналы и нет никаких исключений.Я проверил использование памяти кучи тоже, и она не используется полностью.Даже темы не полностью заняты.(Проверил эту статистику с помощью jconsole).
Если я отключу AOP, удалив <aop:aspectj-autoproxy />
из spring-web-servlet.xml
файла, сервер вернет ответ на все вызовы без каких-либо проблем.
Итак,Я сделал вывод, что включение AOP приводит к зависанию сервера, но я не могу понять, почему.
Любая помощь приветствуется.
ОБНОВЛЕНИЕ
API (контроллер), для которых я пытаюсь вызвать AOP, помечены @PreAuthorize.Если я закомментирую аннотацию @PreAuthorize, приложение не зависнет.Снятие комментария с аннотации @PreAuthorize снова приводит к 5-6 успешным запросам, а затем приложение зависает.Поскольку @PreAuthorize также использует AOP, есть ли какой-то случай, о котором мне нужно позаботиться, когда я использую свой собственный AOP с @PreAuthorize?
UPDATE 2
The @PreAuthorizeМетод API выглядит следующим образом:
@PreAuthorize("hasAuthority('SOME_AUTH') and @myUtil.canRead(#userId) ")
Если я удаляю hasAuthority('SOME_AUTH')
и сохраняю вторую проверку, приложение работает нормально, но если я сохраню обе или оставлю только проверку hasAuthority (), приложениене отвечает после нескольких успешных ответов.
ОБНОВЛЕНИЕ 3
Проблема будет решена, если я аннотирую API с помощью @Transactional.Однако код работал без @Transactional, когда aop был отключен.Так почему включение AOP делает необходимым наличие @Transactional в API?