Monday, 14 August 2023

How to Resolve Circular Dependency in the Spring Framework

    In this tutorial, we will discuss circular dependency in Spring. First, let's understand what a circular dependency is and how to fix it.

What is Circular Dependency in Spring ?

In Spring, a circular dependency occurs when two or more beans depend on each other.

For example, if Class A requires an instance of Class B, and Class B also requires an instance of Class A through any type of dependency injection, a circular dependency is created. In such cases, the Spring IoC container detects the circular reference at runtime and throws a BeanCurrentlyInCreationException.

In Spring Boot, circular dependencies commonly occur when using constructor injection, as shown in the following example:

import org.springframework.stereotype.Component;

@Component
public class BeanA {
    private final BeanB beanB;

    public BeanA(BeanB beanB) {
         this.beanB= beanB;
    }
}

Second bean,
import org.springframework.stereotype.Component;

@Component
public class BeanB {
    private final BeanA beanA;

    public BeanB(BeanA beanA) {
        this.beanA = beanA;
    }
}

Main Application Class,
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoSpringBootApplication{

    public static void main(String[] args) {
        SpringApplication.run(HMSApplication.class);
    }

}

When we run the application using IDE or command(mvn spring-boot:run) during runtime throws below error,

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?

Solution: 

1) Use Setter injection

        As shown in the above example, the circular dependency occurs because constructor injection is used. One way to resolve this issue is to modify the classes to use setter injection instead of constructor injection.

In such cases, avoid constructor injection and use setter injection to break the circular dependency.


import org.springframework.stereotype.Component;

@Component
public class BeanA {
    private final BeanB beanB;

    @Autowired
    public void setBeanB(BeanB beanB) {
         this.beanB= beanB;
    }
}

Second Bean,
import org.springframework.stereotype.Component;

@Component
public class BeanB {
    private final BeanA beanA;
    
    @Autowired
    public void setBeanA(BeanA beanA) {
         this.beanA= beanA;
    }
}

The above approach is not recommended, you can configure circular dependencies with setter injection as well.

2)  Use Lazy Initialization

Another way to resolve a circular dependency is to annotate one of the dependent beans with @Lazy. A bean marked with @Lazy is initialized only when it is first requested, rather than during application startup. This helps break the circular dependency by delaying the creation of one of the beans.

In the previous example, you can apply the @Lazy annotation to the BeanB dependency in the setter method of the BeanA class.


import org.springframework.stereotype.Component;

@Component
public class BeanA {
    private final BeanB beanB;

    @Autowired
    @Lazy
    public void setBeanB(BeanB beanB) {
         this.beanB= beanB;
    }
}


Thank you for visiting the blog.


Reference Post:-

No comments:

Post a Comment