Backend Development 12 min read

Understanding Spring's Circular Dependency Resolution with a Three‑Level Cache

This article explains how Spring solves circular dependencies by using a three‑level cache system, walks through the underlying source‑code execution flow, clarifies the purpose of each cache level, and discusses why the design is essential for AOP‑enabled beans.

Architect
Architect
Architect
Understanding Spring's Circular Dependency Resolution with a Three‑Level Cache

1. Basic Concepts

Spring's circular dependency occurs when two or more beans depend on each other directly or indirectly, forming a loop. The article introduces a simple demo (Louzai1 and Louzai2) that illustrates this classic scenario.

@Service
public class Louzai1 {
    @Autowired
    private Louzai2 louzai2;
    public void test1() {}
}

@Service
public class Louzai2 {
    @Autowired
    private Louzai1 louzai1;
    public void test2() {}
}

1.2 Three‑Level Cache

First‑level cache (singletonObjects) : stores fully initialized singleton beans.

Second‑level cache (earlySingletonObjects) : holds partially created bean instances.

Third‑level cache (singletonFactories) : contains factories that can produce bean proxies.

The execution logic checks the first‑level cache, then the second, and finally the third cache, moving objects between caches as needed.

1.3 Execution Process

The article breaks the process into three nested layers, describing how Spring creates bean A, stores its factory in the third‑level cache, then creates bean B, which depends on A, and finally resolves the circular reference by retrieving A's proxy from the third‑level cache and placing it into the second‑level cache.

2. Source Code Walkthrough

All examples are based on Spring 5.2.15.RELEASE.

2.1 Entry Point

Starting from doGetBean() , Spring attempts to retrieve bean A; not finding it, it proceeds to create the bean.

2.2 First Layer

During doCreateBean() , Spring adds a singleton factory for A into the third‑level cache, then populates properties, invoking the appropriate post‑processor strategy.

2.3 Second Layer

When creating bean B, Spring again calls doGetBean() and discovers B depends on A, leading to the same lookup sequence.

2.4 Third Layer

At this point, the third‑level cache provides a proxy for A, which is stored in the second‑level cache, breaking the circular dependency.

2.5 Returning to Second Layer

After B is fully initialized, its bean is moved from the second‑level cache to the first‑level cache.

2.6 Returning to First Layer

Finally, A is completed, its second‑level entry cleared, and the bean placed into the first‑level cache.

3. Deep Dive into the Principle

3.1 Why Three‑Level Cache?

The first‑level cache guarantees Spring's singleton semantics. The third‑level cache stores factories to break circular references. The second‑level cache is needed when AOP creates proxy objects; it ensures the same proxy instance is reused, preventing multiple instances of the same bean.

3.2 Can the Second‑Level Cache Be Removed?

@Service
public class A {
    @Autowired private B b;
    @Autowired private C c;
}

@Service
public class B {
    @Autowired private A a;
}

@Service
public class C {
    @Autowired private A a;
}

If A has AOP, removing the second‑level cache would cause B and C to obtain different proxy instances (A1 and A2), breaking singleton guarantees. The second‑level cache stores the first proxy so subsequent lookups reuse it.

4. Conclusion

First‑level cache : holds fully initialized singleton beans.

Second‑level cache : stores AOP‑generated proxy beans to maintain singleton behavior.

Third‑level cache : keeps factories for half‑created beans, enabling circular‑dependency resolution.

Understanding these three caches provides a thorough grasp of how Spring resolves circular dependencies and integrates AOP.

Javaaopbackend developmentSpringCircular DependencyThree-level CacheBeanFactory
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.