spring-projects/spring-framework · error · IllegalStateException
MethodInvocation is not a Spring ProxyMethodInvocation: {}
Error message
MethodInvocation is not a Spring ProxyMethodInvocation: {} What it means
Thrown by AbstractAspectJAdvice.currentJoinPoint() (line 80-91) when the current AOP Alliance MethodInvocation obtained from ExposeInvocationInterceptor.currentInvocation() is not an instance of Spring's ProxyMethodInvocation. The code needs a ProxyMethodInvocation to read/set the user attribute holding the JoinPoint. This indicates the advice is executing outside a Spring-managed proxy chain or inside a non-Spring AOP runtime.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java:83
/**
* Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
*/
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
/**
* Lazily instantiate joinpoint for the current invocation.
* Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
* <p>Do not use if access is available to the current ReflectiveMethodInvocation
* (in an around advice).
* @return current AspectJ joinpoint, or through an exception if we're not in a
* Spring AOP invocation.
*/
public static JoinPoint currentJoinPoint() {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation pmi)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
if (jp == null) {
jp = new MethodInvocationProceedingJoinPoint(pmi);
pmi.setUserAttribute(JOIN_POINT_KEY, jp);
}
return jp;
}
private final Class<?> declaringClass;
private final String methodName;
private final Class<?>[] parameterTypes;
protected transient Method aspectJAdviceMethod;
View on GitHub (pinned to e8729d0438)
Solutions
- Ensure the target bean is proxied by Spring (obtained from the ApplicationContext, not via 'new') so the call flows through a Spring ProxyMethodInvocation.
- Add ExposeInvocationInterceptor to the advisor chain / proxy config (the AspectJ advice path requires it) so currentInvocation() returns the Spring proxy type.
- If invoking advice manually in tests, build a ReflectiveMethodInvocation via Spring's infrastructure or call the underlying aspectJAdviceMethod directly instead of currentJoinPoint().
- Remove any foreign interceptor that replaces Spring's MethodInvocation with a non-ProxyMethodInvocation implementation.
Example fix
// before: calling the raw aspect in a test advice.afterReturning(retVal, mi); // mi is a plain org.aopalliance.intercept.MethodInvocation // after: use a Spring ProxyMethodInvocation and register ExposeInvocationInterceptor ProxyFactory pf = new ProxyFactory(target); pf.addAdvice(ExposeInvocationInterceptor.INSTANCE); pf.addAdvice(advice); MyInterface proxy = (MyInterface) pf.getProxy(); proxy.businessMethod();
Defensive patterns
Strategy: validation
Validate before calling
// Before calling currentJoinPoint()-dependent advice logic, verify the invocation type.
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException(
"Cannot use AspectJ join-point binding outside a Spring ProxyMethodInvocation; got " + mi.getClass());
} Type guard
// Guard any advice entry point that relies on currentJoinPoint().
private static boolean isSpringProxyInvocation(MethodInvocation mi) {
return mi instanceof org.springframework.aop.ProxyMethodInvocation;
} Try / catch
try {
JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();
// ...
} catch (IllegalStateException ex) {
if (ex.getMessage().startsWith("MethodInvocation is not a Spring ProxyMethodInvocation")) {
// not in a Spring proxy context; degrade gracefully or re-throw with context
throw new IllegalStateException("Advice invoked outside Spring AOP proxy chain", ex);
}
throw ex;
} Prevention
- Always obtain advised beans from the ApplicationContext so they are Spring proxies.
- Include ExposeInvocationInterceptor in any custom ProxyFactory that uses AspectJ-style advice.
- Do not invoke advice objects directly in tests; drive the proxy instead.
- Avoid mixing non-Spring AOP interceptors on beans that use AspectJ join-point binding.
When it happens
Trigger: Calling currentJoinPoint() (directly or via an advice that delegates to it, e.g. getJoinPoint()/getJoinPointMatch()) when ExposeInvocationInterceptor.currentInvocation() returns a MethodInvocation that is not a ProxyMethodInvocation. This happens when the advice is invoked through a non-Spring proxy, a manually constructed ReflectiveMethodInvocation that is not the Spring proxy variant, or when the proxy was created by a different AOP framework.
Common situations: Mixing Spring AOP with another AOP framework (AspectJ weaving, ByteBuddy interceptors) on the same bean; manually invoking advice objects; unit-testing advice by stubbing MethodInvocation; deserializing/transporting an advice across a context that lost the ExposeInvocationInterceptor in its advice chain.
Related errors
- 'argumentNames' property of AbstractAspectJAdvice contains a
- Only afterReturning advice can be used to bind a return valu
- Only afterThrowing advice can be used to bind a thrown excep
- Advice method [{}] requires {} arguments to be bound by name
- Expecting to find {} arguments to bind by name in advice, bu
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/a8c750e4e22e6eac.json.
Report an issue: GitHub.