为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Spring AOP 时,在单个连接点上绑定参数的多个环绕通知会导致错误

使用 Spring AOP 时,在单个连接点上绑定参数的多个环绕通知会导致错误

斯蒂芬大帝 2021-12-01 16:32:58
我在一个方法上写了 2 个注释和 2 个围绕建议来处理每个注释值。连接点方法是这样的:@CacheFetch(cacheName = CacheManager.CACHE_DATASOURCE_INFO)@TenantAware(method = OperationMethod.OPERATION, operation = OperationType.GET)public DataSourceInfo fetchDataSource(String sourceId) {...}像这样的建议1:@Around("within(com.xx.yy.zz..*) && @annotation(fetch)")public Object fetchFromCache(ProceedingJoinPoint pjp, CacheFetch fetch) throws Throwable {...}Advice2 像这样:@Around("isXXX() && @annotation(tenantAware)")public Object handleTenantAware(ProceedingJoinPoint pjp, TenantAware tenantAware) throws Throwable {...}这两个建议在不同的 Aspect 类中,并且 Aspect 类都实现了 Ordered 接口。当程序到达fetchDataSource连接点方法时,出现异常:java.lang.IllegalStateException: Required to bind 2 arguments, but only bound 1 (JoinPointMatch was NOT bound in invocation)    at org.springframework.aop.aspectj.AbstractAspectJAdvice.argBinding(AbstractAspectJAdvice.java:591)    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671)如果我删除其中一个建议,错误就会消失,而其余的建议可以正常工作。我搜索了这个问题,大部分结果来自非常旧的 spring 版本。我当前的 Spring 框架和方面版本是 4.1.6。我尝试升级到 4.1.9 和 4.3.20,问题仍然存在。恕我直言,上面的代码应该可以工作,我自己也没有发现任何错误。我不确定这是一个错误还是其他我不知道的东西。任何帮助将不胜感激。谢谢你。
查看完整描述

3 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

问题已解决,但仍有问题。

我正在使用 2 个方面类,其顺序设置为Ordered.HIGHEST_PRECEDENCEOrdered.LOWEST_PRECEDENCE。如果我Ordered.HIGHEST_PRECEDENCE用另一个值替换订单值,错误就会消失。相当奇怪的现象,异常显示与实际原因无关。有谁知道真正的原因?


查看完整回答
反对 回复 2021-12-01
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

这是因为ExposeInvocationInterceptor没有先加载,导致userAttributes不会被Spring Bean (for CacheFetch)注入参数。


您也可以在以下位置找到评论:


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!

并且还有一个问题尝试通过使用来解决此问题PriorityOrdered,但似乎仍未解决。


因此,对于您的问题,有两种解决方案可以解决此问题:

  1. 改变OrderedHIGHEST_PRECEDENCE,也许HIGHEST_PRECEDENCE+1

  2. 手动注入 bean ApplicationContext.getBean


查看完整回答
反对 回复 2021-12-01
?
阿晨1998

TA贡献2037条经验 获得超6个赞

我发现了另一种情况,可能会使 中的调用无效Exposeinvocationinterceptor,导致org.springframework.aop.aspectj.aspectjexpressionpointcut ා matches (java.lang.reflect.method, java.lang.class <? >, Java. Lang.Object...)无法获得有效的方法调用。

具体情况:当有多个aspect时,当一个高优先级aspect异步处理时joinpoint.Processed(),下一个aspect会切换到一个新的线程,所以无法获取到ThreadLocal变量。

//img1.sycdn.imooc.com//61a7336b0001459510410870.jpg

查看完整回答
反对 回复 2021-12-01
  • 3 回答
  • 0 关注
  • 426 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信