spring-projects/spring-framework · error · FactoryBeanNotInitializedException

{} does not support circular references

Error message

{} does not support circular references

What it means

AbstractFactoryBean.getObject, when involved in a circular reference, exposes an early singleton proxy via getEarlySingletonInstance; that requires getEarlySingletonInterfaces() to return the interfaces to proxy. The base implementation returns null, so a FactoryBean that does not override getEarlySingletonInterfaces cannot participate in circular references and throws FactoryBeanNotInitializedException.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/AbstractFactoryBean.java:164

	public final T getObject() throws Exception {
		if (isSingleton()) {
			T instance = this.singletonInstance;
			return (instance != null ? instance : getEarlySingletonInstance());
		}
		else {
			return createInstance();
		}
	}

	/**
	 * Determine an 'early singleton' instance, exposed in case of a
	 * circular reference. Not called in a non-circular scenario.
	 */
	@SuppressWarnings("unchecked")
	private T getEarlySingletonInstance() {
		Class<?>[] ifcs = getEarlySingletonInterfaces();
		if (ifcs == null) {
			throw new FactoryBeanNotInitializedException(
					getClass().getName() + " does not support circular references");
		}
		if (this.earlySingletonInstance == null) {
			this.earlySingletonInstance = (T) Proxy.newProxyInstance(
					this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler());
		}
		return this.earlySingletonInstance;
	}

	/**
	 * Expose the singleton instance (for access through the 'early singleton' proxy).
	 * @return the singleton instance that this FactoryBean holds
	 * @throws IllegalStateException if the singleton instance is not initialized
	 */
	private T getSingletonInstance() throws IllegalStateException {
		T instance = this.singletonInstance;
		Assert.state(instance != null, "Singleton instance not initialized yet");
		return instance;

View on GitHub (pinned to e8729d0438)

Solutions

  1. Override getEarlySingletonInterfaces() in your FactoryBean to return the interface(s) the early proxy should implement.
  2. Break the circular dependency (extract a shared collaborator, use @Lazy, setter injection, or restructure).
  3. If circular references are not needed, ensure no cycle exists - the error itself confirms a cycle is present.

Example fix

// before
public class MyFactoryBean extends AbstractFactoryBean<MyService> {
  // getEarlySingletonInterfaces() not overridden
}
// after
@Override
protected Class<?>[] getEarlySingletonInterfaces() {
  return new Class<?>[] { MyService.class };
}
Defensive patterns

Strategy: validation

Validate before calling

if (bean instanceof FactoryBean<?> fb && fb instanceof AbstractFactoryBean<?> afb) {
  if (afb.getEarlySingletonInterfaces() == null) {
    log.warn("FactoryBean {} cannot participate in circular references", fb.getClass());
  }
}

Type guard

boolean supportsCircularRefs(AbstractFactoryBean<?> fb) {
  try { return fb.getEarlySingletonInterfaces() != null; }
  catch (Throwable t) { return false; }
}

Prevention

When it happens

Trigger: A custom FactoryBean (extending AbstractFactoryBean) is part of a bean reference cycle, but the subclass does not override getEarlySingletonInterfaces() to declare which interfaces the early proxy should expose.

Common situations: Two beans mutually depending on each other where at least one is a FactoryBean that leaves getEarlySingletonInterfaces at its default (null); a refactor introduces a cycle involving a FactoryBean.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/dfb991d168925f14.json. Report an issue: GitHub.