猿问

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

我在一个方法上写了 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,问题仍然存在。


恕我直言,上面的代码应该可以工作,我自己也没有发现任何错误。我不确定这是一个错误还是其他我不知道的东西。任何帮助将不胜感激。谢谢你。


斯蒂芬大帝
浏览 451回答 3
3回答

四季花海

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

qq_遁去的一_1

这是因为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,但似乎仍未解决。因此,对于您的问题,有两种解决方案可以解决此问题:改变Ordered不HIGHEST_PRECEDENCE,也许HIGHEST_PRECEDENCE+1手动注入 bean ApplicationContext.getBean

阿晨1998

我发现了另一种情况,可能会使 中的调用无效Exposeinvocationinterceptor,导致org.springframework.aop.aspectj.aspectjexpressionpointcut ා matches (java.lang.reflect.method, java.lang.class <? >, Java. Lang.Object...)无法获得有效的方法调用。具体情况:当有多个aspect时,当一个高优先级aspect异步处理时joinpoint.Processed(),下一个aspect会切换到一个新的线程,所以无法获取到ThreadLocal变量。
随时随地看视频慕课网APP

相关分类

Java
我要回答