2
votes

I wrote 2 annotations on a method and 2 Around advices to process each annotation values.

The join point method is like this:

@CacheFetch(cacheName = CacheManager.CACHE_DATASOURCE_INFO)
@TenantAware(method = OperationMethod.OPERATION, operation = OperationType.GET)
public DataSourceInfo fetchDataSource(String sourceId) {...}

Advice 1 like this:

@Around("within(com.xx.yy.zz..*) && @annotation(fetch)")
public Object fetchFromCache(ProceedingJoinPoint pjp, CacheFetch fetch) throws Throwable {...}

Advice2 like this:

@Around("isXXX() && @annotation(tenantAware)")
public Object handleTenantAware(ProceedingJoinPoint pjp, TenantAware tenantAware) throws Throwable {...}

The 2 advices are in difference Aspect classes and the Aspect classes both implemented Ordered interface. When the program reaches the fetchDataSource join point method, an exception occurs:

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)

If I remove one of the advice, the error disappears, and the remaining advice works correctly. I've searched the issue, and most of the result were from very old spring versions.

My current Spring framework and aspects version is 4.1.6. I tried upgrading to 4.1.9 and 4.3.20, and the issue persists.

IMHO the codes above should work, and I didn't find any mistakes myself. I'm not sure if it is a bug or something else I don't know. Any help will be appreciated. Thank you.

3

3 Answers

2
votes

Problem resolved, but there are still questions.

I was using the 2 aspect classes with order set to Ordered.HIGHEST_PRECEDENCE and Ordered.LOWEST_PRECEDENCE. If I replace the order value Ordered.HIGHEST_PRECEDENCE with another value, the error disappears. Quite weird phenomenon, and the exception showed nothing to do with the actual cause. Does anyone knows the actual reason?

1
votes

This is caused by ExposeInvocationInterceptor not load firstly, and it will cause userAttributes will not inject parameters by Spring Bean(for CacheFetch).

also you can find comment in :

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!

and there is also an issue try to fix this by using PriorityOrdered, but it seems it's still not ongoing.

So for your problem, there are two solutions for solving this:

  1. change the Ordered not HIGHEST_PRECEDENCE, maybe HIGHEST_PRECEDENCE+1

  2. manually inject bean by ApplicationContext.getBean

0
votes

I found another situation that may invalidate the invocation in Exposeinvocationinterceptor, resulting in org.springframework.aop.aspectj.aspectjexpressionpointcut ා matches (java.lang.reflect.method, java.lang.class <? >, Java. Lang.Object...) being unable to obtain a valid methodinvocation.

Specific situation: when there are multiple aspects, when a high priority aspect asynchronously processes joinpoint.Processed(), the next aspect will switch to a new thread, so the ThreadLocal variable cannot be obtained. enter image description here