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.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why Does Spring’s Circular Dependency Fail? Uncovering the Hidden Pitfalls

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

Dependency diagram
Dependency diagram
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.

backend-developmentdependency-injectioncircular-dependency
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.