spring-projects/spring-framework · error · AopConfigException
Can only use global advisors or interceptors with a…
Error message
Can only use global advisors or interceptors with a ListableBeanFactory
What it means
Thrown as AopConfigException by ProxyFactoryBean.initializeAdvisorChain when an interceptorNames entry ends with the global suffix '*' but this.beanFactory is not a ListableBeanFactory. Resolving '*' (or 'prefix*') requires enumerating beans by type, which only ListableBeanFactory supports. The check is at lines 423-427.
Solutions
- Use a ListableBeanFactory (DefaultListableBeanFactory or any ApplicationContext) as the backing factory.
- If you must keep a non-listable factory, replace global patterns ('global*') with explicit bean names in interceptorNames.
Example fix
// before
ProxyFactoryBean fb = new ProxyFactoryBean();
fb.setBeanFactory(nonListableFactory);
fb.setInterceptorNames("global*");
// after
ProxyFactoryBean fb = new ProxyFactoryBean();
fb.setBeanFactory(new DefaultListableBeanFactory()); // ListableBeanFactory
fb.setInterceptorNames("global*");
// or: fb.setInterceptorNames("advisor1","advisor2"); Defensive patterns
Strategy: validation
Validate before calling
if (Arrays.stream(interceptorNames).anyMatch(n -> n.endsWith("*"))
&& !(beanFactory instanceof ListableBeanFactory)) {
throw new IllegalStateException("Global advisor patterns require a ListableBeanFactory");
} Type guard
static boolean supportsGlobals(BeanFactory bf) { return bf instanceof ListableBeanFactory; } Try / catch
try { Object p = pfb.getObject(); }
catch (AopConfigException e) {
if (e.getMessage().contains("ListableBeanFactory")) { /* swap factory or remove '*' names */ }
throw e;
} Prevention
- Use a DefaultListableBeanFactory (any ApplicationContext) when relying on global patterns.
- Avoid '*' patterns in interceptorNames for unit tests that inject minimal bean factories.
When it happens
Trigger: Providing ProxyFactoryBean with a custom BeanFactory that only implements BeanFactory (not ListableBeanFactory) and using a global advisor pattern in interceptorNames. Standard ApplicationContexts use DefaultListableBeanFactory, so this is rare outside custom wiring.
Common situations: Programmatic setup where setBeanFactory is called with a non-listable factory; testing harnesses injecting a minimal BeanFactory stub; legacy custom BeanFactory implementations.
Related errors
- 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…
- Target required after globals
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/f5577b2a69fd0e87.
Report an issue: GitHub.
Appendix: 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 69bf83ad71)