How Spring Resolves Circular Dependencies: A Deep Dive into Bean Creation

This article explains what a circular dependency is in Spring, outlines the conditions under which Spring can resolve such cycles, and details the three‑level cache mechanism that enables bean creation, property injection, and AOP proxy handling to break the loop.

Java Backend Technology
Java Backend Technology
Java Backend Technology
How Spring Resolves Circular Dependencies: A Deep Dive into Bean Creation

What is a circular dependency?

From a literal point of view, it means A depends on B while B also depends on A, or a component depends on itself. In code this looks like:

@Component
public class A {
    // A injects B
    @Autowired
    private B b;
}

@Component
public class B {
    // B injects A
    @Autowired
    private A a;
}

@Component
public class C {
    // C injects itself
    @Autowired
    private C c;
}

All these cases are circular dependencies.

When can Spring handle a circular dependency?

The beans involved must be singleton. Prototype‑scoped beans never trigger this problem.

The injection method cannot be *only* constructor injection. Setter or field injection can break the cycle.

1. Both A and B use setter injection – OK

2. Both A and B use @Autowired field injection – OK

3. Both A and B use constructor injection – NOT resolved

4. A uses setter, B uses constructor – resolved

5. A uses constructor, B uses setter – NOT resolved (order matters)

From the tests we see that circular dependencies can also be solved when constructor injection is present, as long as the overall conditions above are satisfied.

Spring’s Simple Explanation of Circular Dependencies

Creating a Spring bean consists of two parts: the object instance itself and the injection of its properties. Instantiation is performed via reflection; property injection happens afterwards.

The flow can be visualized as:

When ApplicationContext.getBean() is called, Spring first creates a half‑finished bean, stores it in a cache, and later completes the injection once the dependent bean is available.

Advanced Details

The bean creation process has three stages:

Instantiation (new object).

Property injection.

Initialization (aware interfaces, init methods, AOP proxy creation).

Spring solves circular dependencies using a three‑level cache : singletonObjects: first‑level cache holding fully created singletons. earlySingletonObjects: second‑level cache holding beans that are instantiated but not yet injected. singletonFactories: third‑level cache holding factories that can produce early references.

Normal Circular Dependency Diagram

Without AOP, the three‑level cache is not used.

Circular Dependency with AOP

When a bean needs to be proxied, the factory in the third‑level cache creates the proxy early, allowing the dependent bean to receive a reference before full initialization.

Using only a second‑level cache would force immediate proxy creation, which contradicts Spring’s design of applying AOP at the very end of the bean lifecycle.

Interview Q&A

Q: How does Spring solve circular dependencies? A: By using the three‑level cache described above, exposing a bean reference early through singletonFactories and completing property injection later.

Q: Why can’t a two‑level cache replace the three‑level cache? A: Because Spring deliberately delays AOP proxy creation until after bean initialization; a two‑level cache would require early proxy creation, breaking this principle.

Core Process Overview

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaspringdependency-injectioncircular-dependencyThree-level Cachebean-lifecycle
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

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.