Understanding Circular Dependency Issues in Spring IoC and Their Resolution
This article provides a comprehensive overview of Spring IoC circular dependency problems, explains the three types of circular dependencies, demonstrates them with Java and XML code, and details how Spring resolves singleton setter‑based cycles using its three‑level cache mechanism.
The article presents a comprehensive overview of circular dependency problems in Spring's IoC container, explaining what they are, showing diagrams, and providing concrete code examples.
What is a circular dependency? It occurs when class A depends on class B, class B depends on class C, and class C depends back on class A, forming a closed loop.
Below is a demonstration of such a loop using two Java classes with mutual references:
public class ClassA {
private ClassB classB;
public ClassB getClassB() { return classB; }
public void setClassB(ClassB classB) { this.classB = classB; }
}
public class ClassB {
private ClassA classA;
public ClassA getClassA() { return classA; }
public void setClassA(ClassA classA) { this.classA = classA; }
}The corresponding Spring XML configuration that wires the two beans:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="classA" class="ioc.cd.ClassA">
<property name="classB" ref="classB"/>
</bean>
<bean id="classB" class="ioc.cd.ClassB">
<property name="classA" ref="classA"/>
</bean>
</beans>A JUnit test that triggers the circular dependency:
@Test
public void test() throws Exception {
// Create IoC container and initialize
String resource = "spring/spring-ioc-circular-dependency.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(resource);
// Retrieve ClassA instance – circular dependency occurs here
ClassA classA = (ClassA) context.getBean(ClassA.class);
}Spring can encounter three kinds of circular dependencies:
Constructor‑based injection cycles.
Setter‑based injection cycles in prototype (multi‑instance) scope.
Setter‑based injection cycles in singleton scope.
Only the third case (setter injection in singleton scope) is automatically resolved by Spring; the other two result in exceptions.
Spring resolves the singleton setter‑based cycle by using three internal caches:
First‑level cache (singletonObjects) stores fully created singleton bean instances and is exposed to application code.
Second‑level cache (earlySingletonObjects) holds early references to beans that are still being created, used internally by the container.
Third‑level cache (singletonFactories) contains ObjectFactory objects that can create early bean references on demand, which is the key mechanism for breaking the cycle.
The container checks these caches in order (first → second → third) when a bean is requested, allowing it to expose a partially constructed bean early and later replace it with the fully initialized instance.
Understanding these caches, when they are populated, and how they interact is essential for diagnosing and solving circular dependency issues in Spring.
In summary, to master Spring’s circular‑dependency handling you need to know:
The role of each of the three caches.
Why ObjectFactory is used in the third cache.
When the second cache is required.
How and when beans are added to or retrieved from each cache.
What actually gets stored in the first cache when a bean is proxied.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
