{"id":"a8c750e4e22e6eac","repo":"spring-projects/spring-framework","slug":"methodinvocation-is-not-a-spring-proxymethodinvoca","errorCode":null,"errorMessage":"MethodInvocation is not a Spring ProxyMethodInvocation: {}","messagePattern":"MethodInvocation is not a Spring ProxyMethodInvocation: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":83,"sourceCode":"\n\t/**\n\t * Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.\n\t */\n\tprotected static final String JOIN_POINT_KEY = JoinPoint.class.getName();\n\n\n\t/**\n\t * Lazily instantiate joinpoint for the current invocation.\n\t * Requires MethodInvocation to be bound with ExposeInvocationInterceptor.\n\t * <p>Do not use if access is available to the current ReflectiveMethodInvocation\n\t * (in an around advice).\n\t * @return current AspectJ joinpoint, or through an exception if we're not in a\n\t * Spring AOP invocation.\n\t */\n\tpublic static JoinPoint currentJoinPoint() {\n\t\tMethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();\n\t\tif (!(mi instanceof ProxyMethodInvocation pmi)) {\n\t\t\tthrow new IllegalStateException(\"MethodInvocation is not a Spring ProxyMethodInvocation: \" + mi);\n\t\t}\n\t\tJoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);\n\t\tif (jp == null) {\n\t\t\tjp = new MethodInvocationProceedingJoinPoint(pmi);\n\t\t\tpmi.setUserAttribute(JOIN_POINT_KEY, jp);\n\t\t}\n\t\treturn jp;\n\t}\n\n\n\tprivate final Class<?> declaringClass;\n\n\tprivate final String methodName;\n\n\tprivate final Class<?>[] parameterTypes;\n\n\tprotected transient Method aspectJAdviceMethod;\n","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: calling the raw aspect in a test\nadvice.afterReturning(retVal, mi); // mi is a plain org.aopalliance.intercept.MethodInvocation\n// after: use a Spring ProxyMethodInvocation and register ExposeInvocationInterceptor\nProxyFactory pf = new ProxyFactory(target);\npf.addAdvice(ExposeInvocationInterceptor.INSTANCE);\npf.addAdvice(advice);\nMyInterface proxy = (MyInterface) pf.getProxy();\nproxy.businessMethod();","handlingStrategy":"validation","validationCode":"// Before calling currentJoinPoint()-dependent advice logic, verify the invocation type.\nMethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();\nif (!(mi instanceof ProxyMethodInvocation)) {\n    throw new IllegalStateException(\n        \"Cannot use AspectJ join-point binding outside a Spring ProxyMethodInvocation; got \" + mi.getClass());\n}","typeGuard":"// Guard any advice entry point that relies on currentJoinPoint().\nprivate static boolean isSpringProxyInvocation(MethodInvocation mi) {\n    return mi instanceof org.springframework.aop.ProxyMethodInvocation;\n}","tryCatchPattern":"try {\n    JoinPoint jp = AbstractAspectJAdvice.currentJoinPoint();\n    // ...\n} catch (IllegalStateException ex) {\n    if (ex.getMessage().startsWith(\"MethodInvocation is not a Spring ProxyMethodInvocation\")) {\n        // not in a Spring proxy context; degrade gracefully or re-throw with context\n        throw new IllegalStateException(\"Advice invoked outside Spring AOP proxy chain\", ex);\n    }\n    throw ex;\n}","preventionTips":["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."],"tags":["spring-aop","aspectj","proxy","methodinvocation","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}