spring-projects/spring-framework · error · AopConfigException
Target required after globals
Error message
Target required after globals
What it means
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.
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.
Example fix
<!-- before --> <bean id="p" class="...ProxyFactoryBean"> <property name="interceptorNames"><list><value>global*</value></list></property> </bean> <!-- after --> <bean id="p" class="...ProxyFactoryBean"> <property name="targetName" value="serviceImpl"/> <property name="interceptorNames"><list><value>global*</value></list></property> </bean>
Defensive patterns
Strategy: validation
Validate before calling
String[] names = pfb.getInterceptorNames();
if (names != null && names.length > 0 && names[names.length - 1].endsWith("*")
&& pfb.getTargetName() == null && pfb.getTargetSource() == null) {
throw new IllegalStateException("interceptorNames ends with global pattern but no target is set");
} Type guard
static boolean targetSuffixedGlobally(String[] names, ProxyFactoryBean fb) {
return names != null && names.length > 0 && names[names.length-1].endsWith("*")
&& (fb.getTargetName() == null);
} Try / catch
try { Object p = pfb.getObject(); }
catch (AopConfigException e) {
if (e.getMessage().equals("Target required after globals")) { /* set targetName/target */ }
throw e;
} Prevention
- Always set target/targetName when using global advisor patterns.
- Place global patterns earlier in interceptorNames and end with a concrete interceptor/target.
When it happens
Trigger: <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.
Common situations: 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 '*'.
Related errors
- Can only use global advisors or interceptors with a…
- Cannot determine target class for proxy
- No BeanFactory available anymore (probably due to…
- No BeanFactory available anymore (probably due to…
- No BeanFactory available anymore (probably due to…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/24b85361eeee5533.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java:418
}
/**
* Create the advisor (interceptor) chain. Advisors that are sourced
* from a BeanFactory will be refreshed each time a new prototype instance
* is added. Interceptors added programmatically through the factory API
* are unaffected by such changes.
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (!this.advisorChainInitialized && !ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.toString(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory lbf)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisors(lbf, name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.View on GitHub (pinned to 69bf83ad71)