SoFunction
Updated on 2025-03-08

Detailed explanation of Spring's strategy to avoid circular dependencies

Preface

In the Spring framework, circular dependency refers to two or more beans relying on each other to form a closed loop, which may cause BeanCurrentlyInCreationException exception when the application is started. Spring containers support solving the circular dependency problem of constructor injection by default, however, for the way constructor injection, Spring containers cannot handle circular dependencies because it must instantiate the bean first when creating the bean, and circular dependencies prevent it from completing this step. For the way setter injection or field injection, Spring solves the problem of circular dependencies through level 3 cache.

To avoid circular dependencies, the following strategies can be adopted:

1. Use Setter injection instead of constructor injection

Change constructor injection to setter injection or pass@AutowiredAnnotations are injected on fields, allowing Spring containers to instantiate objects first and then set dependencies, thus avoiding circular dependencies during construction.

2. Use @Lazy annotation

For circular dependencies caused by constructor injection, it can be used on dependent constructor parameters@LazyAnnotation, so that the dependent bean is created and injected only when used for the first time.

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

3. How to use Java configuration

Manually control the bean creation process through Java configuration classes, and circular dependencies can be avoided. In a configuration class, you can control the order in which beans are created or delayed by method calls to create a bean.

@Configuration
public class AppConfig {
 
    @Bean
    public A a(B b) {
        return new A(b);
    }
 
    @Bean
    public B b() {
        return new B(a(b()));
    }
}

4. Design pattern solution

In some cases, circular dependencies can be effectively avoided by redesigning the application's architecture or using design patterns (such as mediator pattern, observer pattern, etc.).

5. Decompose cyclic dependencies

Check the components involved in circular dependencies to see if a class can be split into two or more classes to solve the problem of circular dependencies.

6. Use event drivers

Using Spring's event publish-subscribe model to decouple direct dependencies between components, it can effectively avoid circular dependencies.

Overall, avoiding circular dependencies depends primarily on good design and architecture practice. When designing applications, you should pay attention to the dependencies between components and avoid unnecessary direct dependencies to ensure the robustness and maintainability of the application.

This is the end of this article about Spring's strategy of avoiding circular dependencies. For more relevant Spring's content to avoid circular dependencies, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!