spring-projects/spring-framework · error · IllegalStateException
No BeanFactory available anymore (probably due to…
Error message
No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names {} What it means
Thrown as IllegalStateException by ProxyFactoryBean.initializeAdvisorChain when interceptorNames are set but this.beanFactory == null. The beanFactory field is transient, so after deserialization it is null and the factory can no longer resolve interceptor bean names. This signals that a serialized ProxyFactoryBean is being used in a context that lost its BeanFactory.
Solutions
- Do not serialize the ProxyFactoryBean or its proxy across JVMs; instead re-resolve the bean from the BeanFactory after deserialization.
- Mark such beans as non-serializable and store an identifier, then look them up on the other side.
- For sessions, store a stable key and call applicationContext.getBean(name) after deserialization rather than the proxy itself.
- If you must serialize proxies, use a JDK interface proxy with serializable advisors and avoid interceptorNames-based configuration (set advisors directly so no BeanFactory is needed at deserialize time).
Example fix
// before
session.setAttribute("service", aopProxyBean); // serialized later
// after
session.setAttribute("serviceBeanName", "service");
// on read:
MyService svc = appCtx.getBean((String) session.getAttribute("serviceBeanName"), MyService.class); Defensive patterns
Strategy: fallback
Validate before calling
// Before serializing, store a name and look up on the other side
if (bean instanceof Advised) {
// store an identifier, not the proxy
store("svcName", "myService");
} Type guard
static boolean isProxyFactoryBeanDerived(Object o) { return (o instanceof Advised) && Proxy.isProxyClass(o.getClass()); } Try / catch
try { advisors = pfb.getAdvisors(); }
catch (IllegalStateException e) {
if (e.getMessage().contains("serialization")) { /* re-resolve from BeanFactory by name */ }
throw e;
} Prevention
- Never put AOP proxies in distributed sessions/caches; store bean names instead.
- Inline advisors via addAdvisor rather than interceptorNames if serialization is unavoidable.
- For session beans, mark proxies transient and rebuild from the ApplicationContext.
When it happens
Trigger: Serializing a singleton proxy produced by ProxyFactoryBean, deserializing it elsewhere, then triggering re-initialization of the advisor chain (e.g. prototype mode, adviceChanged, or any path that re-enters initializeAdvisorChain with the transient beanFactory now null).
Common situations: Distributed session caches (Redis/Hazelcast with Java serialization) holding a Spring AOP proxy bean; HTTP session replication of proxied beans; passing proxied beans through RMI/JMS; serializing application context state for restart.
Related errors
- No BeanFactory available anymore (probably due to…
- No BeanFactory available anymore (probably due to…
- Can only use global advisors or interceptors with a…
- Cannot determine target class for proxy
- Target required after globals
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/ffe638bf6c399ca7.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/framework/ProxyFactoryBean.java:411
}
// Treat it as a target bean if we can't tell.
if (logger.isDebugEnabled()) {
logger.debug("Could not determine type of bean with name '" + beanName +
"' - assuming it is neither an Advisor nor an Advice");
}
return false;
}
/**
* 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()));
}View on GitHub (pinned to 69bf83ad71)