How Spring’s Three‑Level Cache Solves Circular Dependencies
This article explains what circular dependencies are in Spring, describes the three‑level cache mechanism (singletonObjects, earlySingletonObjects, singletonFactories), shows how it resolves singleton bean cycles, and outlines scenarios where the cache cannot break the dependency, such as constructor injection and prototype beans.
1. What Is a Circular Dependency
When two services, e.g., AService and BService , reference each other, a circular dependency occurs. The article shows typical code snippets (illustrated with diagrams) where each class autowires the other.
2. Scenarios Solved by the Three‑Level Cache
The three‑level cache can resolve the above field‑injection cycle. Setter injection works as well, as shown in the diagram.
3. How Spring Creates a Bean
The bean creation process consists of several stages: BeanDefinition reading, instantiation, property population (where @Autowired is applied), and initialization (including callbacks and proxy creation). The article provides a flow diagram.
4. The Three Levels of Cache
First level (singletonObjects) : stores fully created singleton beans.
Second level (earlySingletonObjects) : holds early‑exposed beans that are not yet fully initialized, enabling circular references.
Third level (singletonFactories) : contains ObjectFactory instances that can produce early beans on demand. This cache works only for singleton beans.
5. How the Cache Breaks the Cycle
When AService is instantiated, its ObjectFactory is placed in the third‑level cache. When BService needs AService , Spring looks through the three caches, finds the factory, obtains the early bean, stores it in the second‑level cache, and injects it into BService . After both beans are fully created, they are moved to the first‑level cache and the secondary caches are cleared.
6. Cases the Cache Cannot Solve
1) Constructor injection : The bean is needed before it is instantiated, so the third‑level cache is never populated, leading to a startup error.
2) Prototype (non‑singleton) beans : The cache works only for singletons; prototype beans trigger an exception when a circular reference is detected.
7. Why Not Use Only Two Levels of Cache?
Removing the third level would force early exposure of bean instances or proxies, which can cause mismatches between early and fully created beans and lead to startup failures. Removing the second level would require repeatedly creating proxies via the factory, also causing inconsistencies. Hence both secondary caches are necessary.
Article ends.
Sanyou's Java Diary
Passionate about technology, though not great at solving problems; eager to share, never tire of learning!
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.