SoFunction
Updated on 2025-05-07

The reasons and solutions for Springboot circular dependencies

What is circular dependency

Circular DependencyIt refers to two or more beans that depend directly or indirectly on each other, causing the container to fail to initialize these beans normally.

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB; // Service dependency}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA; // Service dependency}

Spring Boot is based on the Spring framework, and its circular dependency processing mechanism is consistent with Spring, but it is default in Spring Boot 2.6+ version.Circular dependency is forbidden(pass-circular-references=false)。 

Causes of circular dependencies

1. Constructor injection loop dependencies

@Service
public class ServiceA {
    private final ServiceB serviceB;
    public ServiceA(ServiceB serviceB) { // Constructor injection         = serviceB;
    }
}

@Service
public class ServiceB {
    private final ServiceA serviceA;
    public ServiceB(ServiceA serviceA) { // Constructor injection         = serviceA;
    }
}
  • Report an error directly: The circular dependency injected by the constructor cannot be solved, and it is thrown when the container startsBeanCurrentlyInCreationException

2.Setter/Field Injection Circular Dependencies

Use the @Autowired annotation tag in spring for automatic injection. If it is not processed, a circular dependency problem will occur.

How to solve circular dependencies

Before Springboot 2.5, the circular dependency problem of singleton beans could be solved through level 3 cache.

Cache name Responsibilities
singletonObjects Store fully initialized beans (level one cache)
earlySingletonObjects Store early exposure early beans (L2 cache)
singletonFactories Factory objects that store beans (level three cache)

Taking the original ServiceA and ServiceB as examples,

  • CreateServiceA, through the factoryQuote for semi-finished productsSave into Level 3 cache.

  • ServiceAInjectionServiceB, triggerServiceBCreation of  .

  • CreateServiceB, and also store its semi-finished product reference into the third-level cache.

  • ServiceBInjectionServiceAWhen, get from the third level cacheServiceAEarly quotations, completedServiceBInitialization.

  • ServiceBAfter the initialization is completed,ServiceAComplete dependency injection and finally initialize.

Several solutions after the emergence of circular dependencies:

1.Avoid circular dependencies (recommended)

  • Refactoring the code: Extract the public logic into the third bean.

  • Use interfaces or abstract classes: Decoupling through interface-oriented programming.

2. Allow circular dependencies (temporary scheme)

existCircular dependencies are explicitly allowed:

# Spring Boot 2.6+ requires manual activation-circular-references=true

This only applies to cases where the circular dependencies of Springboot version 2.6 or above are prohibited.

3. use@LazyDelay loading

Add on one of the dependencies@Lazy, Delay injection bean initialization:

@Service
public class ServiceA {
    @Lazy
    @Autowired
    private ServiceB serviceB; // Delay initialization ServiceB}

4. Adjust the injection method

 Priority to Setter/Field injection: Avoid unsolvable circular dependencies caused by constructor injection.

@Service
public class ServiceA {
    private ServiceB serviceB;
    
    @Autowired
    public void setServiceB(ServiceB serviceB) { // Setter injection         = serviceB;
    }
}

Use setter injection

Limitations of cyclic dependency

  • Constructor injection cannot solve circular dependencies: Spring container needs to complete the constructor call first when creating a bean, and the dependency bean has not been initialized at this time.

  • Prototype scoped beans: Spring does not manage the full life cycle of a prototype bean and cannot resolve its circular dependencies.

  • AOP proxy problem: If the bean is proxyed by AOP (such as@Async@Transactional), which may cause circular dependency resolution to fail.

Summarize

The circular dependence essence of Spring Boot is the mechanism problem of the Spring framework. The core solution is:

  • Understand how Level 3 caching works.

  • Priority is given to avoid circular dependencies through code design.

  • Use reasonably if necessary@LazyOr adjust the injection method.

Avoid circular dependencies at the beginning of design as much as possible

This is the end of this article about the reasons and solutions of Springboot circular dependencies. For more related Springboot circular dependencies, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!