{"record":{"id":"24b85361eeee5533","repo":"spring-projects/spring-framework","slug":"target-required-after-globals","errorCode":null,"errorMessage":"Target required after globals","messagePattern":"Target required after globals","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java","lineNumber":418,"sourceCode":"\t}\n\n\t/**\n\t * Create the advisor (interceptor) chain. Advisors that are sourced\n\t * from a BeanFactory will be refreshed each time a new prototype instance\n\t * is added. Interceptors added programmatically through the factory API\n\t * are unaffected by such changes.\n\t */\n\tprivate synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {\n\t\tif (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {\n\t\t\tif (this.beanFactory == null) {\n\t\t\t\tthrow new IllegalStateException(\"No BeanFactory available anymore (probably due to serialization) \" +\n\t\t\t\t\t\t\"- cannot resolve interceptor names \" + Arrays.toString(this.interceptorNames));\n\t\t\t}\n\n\t\t\t// Globals can't be last unless we specified a targetSource using the property...\n\t\t\tif (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&\n\t\t\t\t\tthis.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {\n\t\t\t\tthrow new AopConfigException(\"Target required after globals\");\n\t\t\t}\n\n\t\t\t// Materialize interceptor chain from bean names.\n\t\t\tfor (String name : this.interceptorNames) {\n\t\t\t\tif (name.endsWith(GLOBAL_SUFFIX)) {\n\t\t\t\t\tif (!(this.beanFactory instanceof ListableBeanFactory lbf)) {\n\t\t\t\t\t\tthrow new AopConfigException(\n\t\t\t\t\t\t\t\t\"Can only use global advisors or interceptors with a ListableBeanFactory\");\n\t\t\t\t\t}\n\t\t\t\t\taddGlobalAdvisors(lbf, name.substring(0, name.length() - GLOBAL_SUFFIX.length()));\n\t\t\t\t}\n\n\t\t\t\telse {\n\t\t\t\t\t// If we get here, we need to add a named interceptor.\n\t\t\t\t\t// We must check if it's a singleton or prototype.\n\t\t\t\t\tObject advice;\n\t\t\t\t\tif (this.singleton || this.beanFactory.isSingleton(name)) {\n\t\t\t\t\t\t// Add the real Advisor/Advice to the chain.","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java#L400-L436","documentation":"Thrown as AopConfigException by ProxyFactoryBean.initializeAdvisorChain when the last entry in interceptorNames ends with the global suffix '*' but there is no target (targetName == null and targetSource is the empty default). Global advisor patterns expand to zero or more advisors; if they are last, there is nothing for the chain to delegate to, which is almost certainly a configuration mistake.","triggerScenarios":"<property name=\"interceptorNames\"><list><value>global*</value></list></property> with no target/targetSource/targetName. The check at lines 416-418 fires because the trailing global pattern cannot serve as the target.","commonSituations":"XML config with a single 'global*' interceptor name and the target set on a different property that was renamed/removed; refactoring that dropped the target property but left interceptorNames ending in '*'.","solutions":["Add a real target: set <property name=\"targetName\" value=\"myServiceImpl\"/> (or target / targetSource).","Append a concrete interceptor name or the target bean name after the global* entry so the global is not last.","Move global advisor patterns earlier in the list and end with a specific target or interceptor."],"exampleFix":"<!-- before -->\n<bean id=\"p\" class=\"...ProxyFactoryBean\">\n  <property name=\"interceptorNames\"><list><value>global*</value></list></property>\n</bean>\n\n<!-- after -->\n<bean id=\"p\" class=\"...ProxyFactoryBean\">\n  <property name=\"targetName\" value=\"serviceImpl\"/>\n  <property name=\"interceptorNames\"><list><value>global*</value></list></property>\n</bean>","handlingStrategy":"validation","validationCode":"String[] names = pfb.getInterceptorNames();\nif (names != null && names.length > 0 && names[names.length - 1].endsWith(\"*\")\n    && pfb.getTargetName() == null && pfb.getTargetSource() == null) {\n  throw new IllegalStateException(\"interceptorNames ends with global pattern but no target is set\");\n}","typeGuard":"static boolean targetSuffixedGlobally(String[] names, ProxyFactoryBean fb) {\n  return names != null && names.length > 0 && names[names.length-1].endsWith(\"*\")\n      && (fb.getTargetName() == null);\n}","tryCatchPattern":"try { Object p = pfb.getObject(); }\ncatch (AopConfigException e) {\n  if (e.getMessage().equals(\"Target required after globals\")) { /* set targetName/target */ }\n  throw e;\n}","preventionTips":["Always set target/targetName when using global advisor patterns.","Place global patterns earlier in interceptorNames and end with a concrete interceptor/target."],"tags":["spring-aop","proxyfactorybean","configuration","global-advisors"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}