{"id":"f758ec5beb859e92","repo":"spring-projects/spring-framework","slug":"dynamicintroductionadvice-may-only-be-added-as-par","errorCode":null,"errorMessage":"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor","messagePattern":"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java","lineNumber":444,"sourceCode":"\tpublic void addAdvice(Advice advice) throws AopConfigException {\n\t\tint pos = this.advisors.size();\n\t\taddAdvice(pos, advice);\n\t}\n\n\t/**\n\t * Cannot add introductions this way unless the advice implements IntroductionInfo.\n\t */\n\t@Override\n\tpublic void addAdvice(int pos, Advice advice) throws AopConfigException {\n\t\tAssert.notNull(advice, \"Advice must not be null\");\n\t\tif (advice instanceof IntroductionInfo introductionInfo) {\n\t\t\t// We don't need an IntroductionAdvisor for this kind of introduction:\n\t\t\t// It's fully self-describing.\n\t\t\taddAdvisor(pos, new DefaultIntroductionAdvisor(advice, introductionInfo));\n\t\t}\n\t\telse if (advice instanceof DynamicIntroductionAdvice) {\n\t\t\t// We need an IntroductionAdvisor for this kind of introduction.\n\t\t\tthrow new AopConfigException(\"DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor\");\n\t\t}\n\t\telse {\n\t\t\taddAdvisor(pos, new DefaultPointcutAdvisor(advice));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean removeAdvice(Advice advice) throws AopConfigException {\n\t\tint index = indexOf(advice);\n\t\tif (index == -1) {\n\t\t\treturn false;\n\t\t}\n\t\telse {\n\t\t\tremoveAdvisor(index);\n\t\t\treturn true;\n\t\t}\n\t}\n","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L426-L462","documentation":"Thrown by AdvisedSupport.addAdvice(int, Advice) when the supplied Advice is a DynamicIntroductionAdvice but does not implement IntroductionInfo. Dynamic introductions (which add new interfaces/behavior to a target) require an IntroductionAdvisor to describe the interfaces being introduced, because the framework cannot infer them from a bare DynamicIntroductionAdvice. Spring routes self-describing IntroductionInfo instances through a DefaultIntroductionAdvisor automatically, but rejects bare DynamicIntroductionAdvice to avoid creating an incomplete introduction.","triggerScenarios":"Passing a custom DynamicIntroductionAdvice implementation that implements neither IntroductionInfo nor is wrapped in an IntroductionAdvisor; using an old advice type that mixes introduction semantics without metadata.","commonSituations":"Authoring a custom mixin/introduction advice and forgetting to implement IntroductionInfo or to wrap it in DefaultIntroductionAdvisor; porting advice from frameworks that bundle introduction differently.","solutions":["Wrap the DynamicIntroductionAdvice in a DefaultIntroductionAdvisor: new DefaultIntroductionAdvisor(advice, IntroductionInfo-implementation).","Have your advice class implement IntroductionInfo (or DelegatingIntroductionInterceptor) so addAdvice can auto-wrap it.","Use addAdvisor(new DefaultIntroductionAdvisor(...)) directly instead of addAdvice for introductions."],"exampleFix":"// before\nDynamicIntroductionAdvice myIntro = ...;  // no IntroductionInfo\nadvised.addAdvice(myIntro);  // throws\n\n// after\nimport org.springframework.aop.support.DefaultIntroductionAdvisor;\nadvised.addAdvisor(new DefaultIntroductionAdvisor(myIntro, MyInterface.class));","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean needsIntroductionInfo(Advice advice) {\n  return advice instanceof org.springframework.aop.DynamicIntroductionAdvice\n      && !(advice instanceof org.springframework.aop.IntroductionInfo);\n}","tryCatchPattern":null,"preventionTips":["Implement IntroductionInfo (or extend DelegatingIntroductionInterceptor) on custom introduction advice.","Wrap dynamic introductions in DefaultIntroductionAdvisor before adding.","Use addAdvisor for introductions rather than addAdvice to make the contract explicit."],"tags":["spring-aop","introduction","advisor","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}