Monday, 14 August 2023

How to resolve circular dependency in spring Framework

 In this tutorial, we can dsicuss about circular dependency in Spring, first need to understand what's the circular dependency and how to fix it.

What is Circular Dependency in Spring ?

In Spring, circular dependency is a dependency chain where two or more beans depends on each other.

For example - Class A requires an instance of class B and class B also requires an instance of class A through any type of injection. In this case, the Spring IoC container detects circular reference at runtime, and throws a BeanCurrentlyInCreationException.

In Spring Boot, circular dependency can occur when using the constructor injection as see below code,

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 see in the above example about circular dependency as there used construction injection so here the solution is to edit the source code of the class to be configured by setter injection instead of constructor injection.
       In such example need to avoid constructor injection and to use setter injection only. 

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

One of the dependency bean to define as @Lazy so it will load the bean whenever it's called. It's not being intialized during the application start up. So this is one of the way to handle the circular dependency issue.

In the previous example, need to use @Lazy annotation at BeanA class with BeanB setter injenction.

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