spring-projects/spring-framework · error · AopConfigException
Can only use global advisors or interceptors with a Listable
Error message
Can only use global advisors or interceptors with a ListableBeanFactory
What it means
Global advisors/interceptors (entries in interceptorNames ending with '*') are resolved by enumerating beans of type Advisor/Interceptor in the BeanFactory via BeanFactoryUtils.beanNamesForTypeIncludingAncestors, which requires ListableBeanFactory. If the injected beanFactory is not listable, addGlobalAdvisors cannot run and AopConfigException is thrown.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java:425
*/
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.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}View on GitHub (pinned to e8729d0438)
Solutions
- Run the ProxyFactoryBean inside a Spring ApplicationContext so it receives a ListableBeanFactory (DefaultListableBeanFactory).
- Remove the '*' global entries from interceptorNames and name advisors explicitly.
- If providing a custom BeanFactory programmatically, ensure it implements ListableBeanFactory.
Example fix
// before
proxyFactoryBean.setBeanFactory(simpleBeanFactory); // not listable
proxyFactoryBean.setInterceptorNames(new String[]{"global*"});
// after
proxyFactoryBean.setBeanFactory(applicationContext); // ListableBeanFactory
// or name explicitly
proxyFactoryBean.setInterceptorNames(new String[]{"txAdvice","secAdvice"}); Defensive patterns
Strategy: validation
Validate before calling
boolean usesGlobals = java.util.Arrays.stream(pfb.getInterceptorNames() == null ? new String[0] : pfb.getInterceptorNames())
.anyMatch(n -> n.endsWith("*"));
if (usesGlobals && !(beanFactory instanceof org.springframework.beans.factory.ListableBeanFactory)) {
throw new IllegalStateException("Global advisors require a ListableBeanFactory");
} Prevention
- Run ProxyFactoryBean inside an ApplicationContext so it gets a ListableBeanFactory.
- Avoid global '*' entries; name advisors explicitly.
- When providing a custom BeanFactory, make sure it implements ListableBeanFactory.
When it happens
Trigger: ProxyFactoryBean is wired with a BeanFactory that is only org.springframework.beans.factory.BeanFactory (or a minimal custom impl) rather than ListableBeanFactory, while interceptorNames contains a global '*' entry.
Common situations: Custom integration where ProxyFactoryBean.setBeanFactory receives a non-listable factory; embedding an AOP proxy in a non-standard container; misusing ProxyFactoryBean outside an ApplicationContext (which always provides a listable factory).
Related errors
- No BeanFactory available anymore (probably due to serializat
- Target required after globals
- Cannot determine target class for proxy
- No BeanFactory available anymore (probably due to serializat
- No BeanFactory available anymore (probably due to serializat
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/f5577b2a69fd0e87.json.
Report an issue: GitHub.