Why Does Spring’s Circular Dependency Fail? Uncovering the Hidden Pitfalls
This article explains the atypical Spring circular‑dependency problem, distinguishes strong and weak dependencies, shows how @Configuration classes turn weak dependencies into strong ones, analyzes bean‑initialisation order, and offers a concrete rule to avoid unresolvable circular references.
Introduction
During recent work I encountered an unusual Spring circular‑dependency issue that is rarely discussed online. I call it the "atypical Spring circular‑dependency problem" and record it here for future reference.
What Is a Dependency?
A dependency means that some functionality of class A requires functionality from class B. There are two levels:
Strong dependency : Creating an instance of A itself needs B (e.g., a mother giving birth to you).
Weak dependency : A can be created without B, but its methods call B (e.g., men plow, women weave).
Correspondingly, circular dependencies can be:
Strong‑dependency cycles.
Weak‑dependency cycles.
Dependency Mediation
Strong dependencies cannot be mediated; weak dependencies can be resolved automatically by Spring’s dependency‑injection (DI) container.
Why Use Dependency Injection?
DI decouples construction, configuration, and initialization logic, allowing the container to resolve weak dependencies and avoid manual constructor‑based wiring that often leads to unresolvable cycles.
Spring’s Dependency‑Injection Model
Class construction (instantiate via no‑arg constructor).
Class configuration (inject fields/getters based on annotations).
Class initialization logic (invoke @PostConstruct, InitializingBean, etc.).
Problem Scenario
The following simplified code demonstrates the issue (all classes are in the same package):
@SpringBootApplication
@Import({ServiceA.class, ConfigurationA.class, BeanB.class})
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
} public class ServiceA {
@Autowired private BeanA beanA;
@Autowired private BeanB beanB;
} public class ConfigurationA {
@Autowired public BeanB beanB;
@Bean public BeanA beanA() { return new BeanA(); }
} public class BeanA {} public class BeanB {
@Autowired public BeanA beanA;
}Running this code results in:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
Although all injections are field‑based (weak), Spring cannot resolve the cycle because of the way the @Configuration class participates.
Root Cause Analysis
A @Configuration class is itself a bean, but it also declares other beans. Spring must fully satisfy the configuration class’s own dependencies before it can create the beans it defines. Consequently, any bean that depends on a bean defined inside a configuration class acquires a strong dependency on that configuration class.
Loading BeanA First
Spring creates ServiceA, sees a dependency on BeanA, tries to load BeanA.
BeanA is defined in ConfigurationA, so Spring loads ConfigurationA.
ConfigurationA depends on BeanB, so Spring loads BeanB.
BeanB depends on BeanA, which is still not created → circular reference → failure.
Loading BeanB First
Spring creates ServiceA, sees a dependency on BeanB, loads BeanB.
BeanB depends on BeanA, so Spring loads BeanA.
BeanA is defined in ConfigurationA, so Spring loads ConfigurationA.
ConfigurationA’s dependency on BeanB is already satisfied, so ConfigurationA is completed.
BeanA can now be created, BeanB receives BeanA, and ServiceA receives both beans – initialization succeeds.
Conclusion
Except for constructor injection, which creates strong dependencies, any bean also strongly depends on the @Configuration class that declares it.
Code Smell & Recommendation
Injecting fields into @Configuration classes effectively adds a strong dependency to every bean it defines, dramatically increasing the risk of unresolvable circular dependencies. The recommended practice is:
Do not perform field‑level injection in classes annotated with @Configuration.
References
Circular Dependencies in Spring
Spring‑bean circular dependency and solutions
Factory method injection should be used in "@Configuration" classes
Illustration
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 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!
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.
