How to Detect and Resolve Circular Dependencies in Spring Boot

This article explains what circular dependencies are in Spring Boot, describes the symptoms and errors introduced in recent versions, and provides multiple practical solutions—including constructor injection, @Lazy, @DependsOn, and interface segregation—along with clear code examples for each approach.

Programmer DD
Programmer DD
Programmer DD
How to Detect and Resolve Circular Dependencies in Spring Boot

What is a Circular Dependency?

Circular dependency occurs when two or more classes in a Spring Boot application depend on each other, forming a loop that prevents proper initialization.

Problem and Symptoms

Before Spring Boot 2.6.0, the framework automatically resolved circular dependencies. Starting with version 2.6.0, circular dependencies are detected by default and cause the application to fail to start.

Example of a circular dependency:

ComponentA class injects ComponentB class, and ComponentB class injects ComponentA class, creating a loop.

ComponentA

import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class ComponentA {
    @Resource
    private ComponentB componentB;
}

ComponentB

import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class ComponentB {
    @Resource
    private ComponentA componentA;
}

Error Message

***************************
APPLICATION FAILED TO START
***************************

Description:
The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  componentA
↑     ↓
|  componentB
└─────┘

Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, you may set spring.main.allow-circular-references to true.

Solutions

Circular dependencies can arise from constructor, property, or method injection. Spring Boot offers several ways to break the cycle:

Constructor Injection: Inject dependencies via constructors instead of fields.

Setter Injection: Use setter methods for injection.

Lazy Injection: Annotate a dependency with @Lazy to defer its initialization.

@Autowired(required = false): Set the required attribute to false to make the injection optional.

@DependsOn: Specify bean initialization order with @DependsOn.

Constructor Injection Example

Original classes with setter injection:

public class A {
    private B b;
    public void setB(B b) { this.b = b; }
}

public class B {
    private A a;
    public void setA(A a) { this.a = a; }
}

Refactored using constructor injection to avoid the cycle:

public class A {
    private final B b;
    public A(B b) { this.b = b; }
}

public class B {
    private final A a;
    public B(A a) { this.a = a; }
}

Lazy Injection Example

Using @Lazy on one side of the dependency:

@Component
public class A {
    private final B b;
    public A(@Lazy B b) { this.b = b; }
}

@Component
public class B {
    private final A a;
    public B(A a) { this.a = a; }
}

Interface Segregation Example

Define a common interface and inject it instead of the concrete classes:

public interface Service {
    void doSomething();
}

public class A {
    private final Service service;
    public A(Service service) { this.service = service; }
}

public class B {
    private final Service service;
    public B(Service service) { this.service = service; }
}

@Service
public class ServiceImpl implements Service {
    private final A a;
    private final B b;
    public ServiceImpl(A a, B b) { this.a = a; this.b = b; }
    @Override
    public void doSomething() { /* ... */ }
}
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.

JavaBackend DevelopmentSpring Bootdependency-injectioncircular-dependency@Lazy
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.