我有一个启用的Spring AOP用于我的日志记录目的,并使用webflux作为API入口点,如果api不像我的login
api那样通过ReactiveAuthenticationManager
,事情就可以正常工作,但当它必须通过ReactiveAuthenticationManager
时,它会抛出下面的异常
java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP invocation is in progress and that the ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() must be invoked from the same thread.
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.currentInvocation(ExposeInvocationInterceptor.java:74) ~[spring-aop-5.3.23.jar:5.3.23]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ Handler com.ums.api.contoller.Controller#getAllUser() [DispatcherHandler]
我的AOP类
public class LoggerAspect {
@Pointcut("within(com.ums..*)")
public void logEveryFunction() {
}
@Before(value = "logEveryFunction()")
public void log(JoinPoint joinPoint) {
log.info("Entering function {} in location {}", joinPoint.getSignature(), joinPoint.getSourceLocation());
}
@After(value = "logEveryFunction()")
public void logEnd(JoinPoint joinPoint) {
log.info("Exiting function {}", joinPoint.getSignature());
}
}
认证功能
public Mono<Authentication> authenticate(Authentication authentication) {
return Mono.justOrEmpty(authentication.getCredentials().toString())
.map(value -> {
return new UsernamePasswordAuthenticationToken(
authentication.getName(),
null,
Arrays.asList(new SimpleGrantedAuthority("VIEW"))
});
}
如何使我的AOP与webflux一起工作?如何解决这个问题?
1条答案
按热度按时间u5i3ibmn1#
让我们再次阅读错误信息:
所以让我们尝试在方面添加一个
@Order
注解。但首先,一些研究。你可以检查Javadocs,我只是检查了源代码:结论:默认顺序为
LOWEST_PRECEDENCE
,i。即Integer.MAX_VALUE
。因此,让我们分配一个更高的优先级,即。即小于Integer.MAX_VALUE
的东西。对于GitHub上的简单示例,以下任何一个都可以:@Order(Integer.MAX_VALUE - 1)
、@Order(0)
或任何您认为适合您情况的内容。将其添加到aspect类后,调用者将在控制台上看到以下内容:Spring服务器日志会说:
更新,回应此后续问题:
我仍然想知道为什么会发生这种情况,为什么需要
@Order
?只有一个建议(从我的AOP),其他将运行?如果您从返回
Mono
的登录方法中删除@PreAuthorize
,那么它在方面没有@Order
注解的情况下也可以工作。这给了你一个线索:SpringSecurity似乎也使用了AOP或者至少是某种方法拦截器。让我们更详细地看看实际错误:请注意堆栈跟踪中的
org.springframework.security.access.prepost.PrePostAdviceReactiveMethodInterceptor
。显然,在Spring Security中,有一个用于响应式方法的特殊方法拦截器。正如你和我之前发布的错误消息中所描述的,这个拦截器似乎需要拦截器/建议链的特殊排序。我猜,这是某种 Bootstrap 问题,希望合并Spring AOP,Spring Security和WebFlux的用户需要适应。