{"record":{"id":"9e455ff165dc1197","repo":"spring-projects/spring-framework","slug":"dynamicintroductionadvice-advice-does-not-impl","errorCode":null,"errorMessage":"DynamicIntroductionAdvice [{advice}] does not implement interface [{ifc.getName()}] specified for introduction","messagePattern":"DynamicIntroductionAdvice \\[(.+?)\\] does not implement interface \\[(.+?)\\] specified for introduction","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/support/DefaultIntroductionAdvisor.java","lineNumber":117,"sourceCode":"\tpublic void addInterface(Class<?> ifc) {\n\t\tAssert.notNull(ifc, \"Interface must not be null\");\n\t\tif (!ifc.isInterface()) {\n\t\t\tthrow new IllegalArgumentException(\"Specified class [\" + ifc.getName() + \"] must be an interface\");\n\t\t}\n\t\tthis.interfaces.add(ifc);\n\t}\n\n\t@Override\n\tpublic Class<?>[] getInterfaces() {\n\t\treturn ClassUtils.toClassArray(this.interfaces);\n\t}\n\n\t@Override\n\tpublic void validateInterfaces() throws IllegalArgumentException {\n\t\tfor (Class<?> ifc : this.interfaces) {\n\t\t\tif (this.advice instanceof DynamicIntroductionAdvice dynamicIntroductionAdvice &&\n\t\t\t\t\t!dynamicIntroductionAdvice.implementsInterface(ifc)) {\n\t\t\t\tthrow new IllegalArgumentException(\"DynamicIntroductionAdvice [\" + this.advice + \"] \" +\n\t\t\t\t\t\t\"does not implement interface [\" + ifc.getName() + \"] specified for introduction\");\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setOrder(int order) {\n\t\tthis.order = order;\n\t}\n\n\t@Override\n\tpublic int getOrder() {\n\t\treturn this.order;\n\t}\n\n\t@Override\n\tpublic Advice getAdvice() {\n\t\treturn this.advice;\n\t}","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/support/DefaultIntroductionAdvisor.java#L99-L135","documentation":"Thrown by DefaultIntroductionAdvisor.validateInterfaces() when the configured advice implements DynamicIntroductionAdvice but does not claim to implement one of the interfaces registered for introduction via implementsInterface(ifc). Spring AOP requires a dynamic introduction advice to declare which interfaces it can dispatch, because it routes introduced method calls through the advice itself rather than a separate delegate.","triggerScenarios":"Constructing new DefaultIntroductionAdvice(advice, ifc) where 'advice' is a DynamicIntroductionAdvice (e.g. a custom IntroductionInterceptor) whose implementsInterface(...) returns false for 'ifc', then the proxy factory calls validateInterfaces() during advisor validation (ProxyFactory.addAdvisor / creation of the proxy).","commonSituations":"Passing the wrong interface class to the two-arg DefaultIntroductionAdvisor constructor; forgetting to implement IntroductionInfo / the interface on a custom IntroductionInterceptor; a typo in the interface class; mixing up DelegatingIntroductionInterceptor (which auto-detects interfaces from the delegate) with a pure DynamicIntroductionAdvice that must declare its own.","solutions":["Make the advice class implement the interface passed to the advisor (or return true from implementsInterface for it).","Use the one-arg DefaultIntroductionAdvisor(advice) constructor when the advice itself implements IntroductionInfo so interfaces are detected automatically.","Switch to DelegatingIntroductionInterceptor with a delegate that implements the interface, so the framework derives the interface list from the delegate.","Double-check that the interface passed to the constructor exactly matches (same Class<?> reference) what the advice advertises."],"exampleFix":"// before\nnew DefaultIntroductionAdvisor(myInterceptor, Lockable.class) // myInterceptor does not implement Lockable\n\n// after\npublic class MyInterceptor implements Lockable, IntroductionInterceptor { ... }\nnew DefaultIntroductionAdvisor(myInterceptor, Lockable.class);","handlingStrategy":"validation","validationCode":"// before building the advisor\nAdvice advice = ...;\nClass<?> ifc = ...;\nif (advice instanceof DynamicIntroductionAdvice dia && !dia.implementsInterface(ifc)) {\n    throw new IllegalStateException(\"advice does not implement \" + ifc.getName());\n}\nnew DefaultIntroductionAdvisor((DynamicIntroductionAdvice) advice, ifc);","typeGuard":"static boolean adviceImplements(Advice a, Class<?> ifc) {\n    return a instanceof DynamicIntroductionAdvice d && d.implementsInterface(ifc);\n}","tryCatchPattern":null,"preventionTips":["Prefer the single-arg DefaultIntroductionAdvisor(advice) when the advice implements IntroductionInfo so interfaces are auto-detected.","Add a unit test asserting your IntroductionInterceptor.implementsInterface(ifc) returns true for every introduced interface.","Use DelegatingIntroductionInterceptor to derive the interface list from a concrete delegate."],"tags":["spring-aop","introduction","advisor","misconfiguration"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}