How Does Spring Detect and Resolve Circular Bean Dependencies?
This article explains what circular dependencies are in Spring, how the framework detects them using a three‑level cache during bean creation, and walks through a step‑by‑step example of resolving a setter‑injected circular reference between two beans.
What is a circular dependency in Spring?
Circular dependency occurs when two or more beans depend on each other, forming a closed loop, e.g., Bean A depends on Bean B and Bean B depends on Bean A, which can prevent the application from starting.
How does Spring discover circular dependencies?
Spring uses a dependency graph to detect circular dependencies. The process includes:
1. Bean creation process
During container startup, Spring scans configuration files or annotations and attempts to create bean instances. The creation steps are:
Instantiation: create bean instance.
Property population: inject dependencies.
Initialization: run custom init methods.
2. Dependency injection process
During property population, Spring injects the bean's dependencies and tracks beans currently being created to detect cycles.
3. Circular dependency detection mechanism
Spring uses DefaultSingletonBeanRegistry to track singleton bean creation status, maintaining three caches:
singletonObjects: first‑level cache for fully initialized beans.
earlySingletonObjects: second‑level cache for early‑exposed singleton beans to resolve circular dependencies.
singletonFactories: third‑level cache storing factories for creating bean instances.
Specific detection steps
Instantiation phase
When Spring starts instantiating a bean, it marks the bean as "currently in creation" by adding its name to the singletonCurrentlyInCreation set.
Property population phase
Spring injects the bean's dependencies and checks whether each dependent bean is already in creation.
If the dependent bean is already being created, Spring detects a circular dependency and handles it based on the injection type.
Constructor injection leads to BeanCurrentlyInCreationException because the cycle cannot be resolved.
Setter injection allows Spring to retrieve the dependent bean from earlySingletonObjects or singletonFactories, exposing a partially created bean to break the cycle.
Example
Consider Bean A and Bean B with circular dependency.
Spring's dependency injection steps:
1. Instantiate Bean A
Mark Bean A as currently in creation and add to singletonCurrentlyInCreation.
Instantiate Bean A and place its factory in the third‑level cache singletonFactories.
2. Populate Bean A's properties
Detect that Bean A depends on Bean B, start creating Bean B.
Mark Bean B as currently in creation and add to singletonCurrentlyInCreation.
Instantiate Bean B and place its factory in singletonFactories.
3. Populate Bean B's properties
Detect Bean B depends on Bean A, which is already in creation, thus a circular dependency is found.
Because injection is via setter, Spring obtains a partially created Bean A from singletonFactories, exposes it in earlySingletonObjects.
Use this partial Bean A to populate Bean B's properties.
4. Complete Bean B creation
After all properties of Bean B are populated, move its instance from singletonFactories to singletonObjects (fully initialized).
5. Return to Bean A creation
Continue populating Bean A's properties; now the full Bean B instance is available from singletonObjects.
Finish Bean A creation and move it from singletonFactories to singletonObjects.
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.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
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.
