我有一个Spring 5.0.4应用程序,其Dispatcher servlet配置文件为spring-web-servlet.xml
(spring-web是Dispatcher servlet名称)。
为了在应用程序中启用AOP,在包含aop的名称空间之后,我在<aop:aspectj-autoproxy />
中创建了条目spring-web-servlet.xml
。
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>
要使用AOP,我在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:aspectj-autoproxy />
文件中删除spring-web-servlet.xml
来禁用AOP,则服务器将返回所有呼叫的响应,而不会出现任何问题。
因此,我得出的启用AOP的结论导致服务器挂起,但我无法理解原因。
感谢您的帮助。
更新
我要在其上调用AOP的API(控制器)用@PreAuthorize注释。如果我注释掉@PreAuthorize批注,则该应用程序不会挂起。再次取消对@PreAuthorize注释的注释会导致5-6个成功的请求,然后应用程序挂起。 由于@PreAuthorize也使用AOP,因此在将我自己的AOP与@PreAuthorize一起使用时,是否需要处理任何情况?
更新2
API上的@PreAuthorize方法如下:
@PreAuthorize("hasAuthority('SOME_AUTH') and @myUtil.canRead(#userId) ")
如果我删除hasAuthority('SOME_AUTH')
并保留第二个检查,则应用程序工作正常,但是如果我同时保留或仅保留hasAuthority()检查,则应用程序在几次成功响应后不会响应。
更新3
如果我使用@Transactional注释API,此问题将得到解决。 但是,禁用aop时,该代码过去无需@Transactional即可工作。那么为什么启用AOP使得必须在API上使用@Transactional?