I have written a program to resolve circular dependencies using setter-based dependency injection. But the output is somewhat confusing.
CODE
package com.spring.core.di;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@ComponentScan("com.spring.core.di")
class CoolAppConfig {
}
@Component
class DependencyA {
DependencyB dependencyB;
public DependencyA() {
System.out.println("I am constructor of Dependency A");
}
@Autowired
public void setDependencyB(@Qualifier("dependencyB") DependencyB dependencyB) {
System.out.println("I am setDependencyB !");
this.dependencyB = dependencyB;
}
public void say() {
this.dependencyB.who();
}
public void who() {
System.out.println("I am Dependency A");
}
}
@Component
class DependencyB {
DependencyA dependencyA;
public DependencyB() {
System.out.println("I am constructor of Dependency B");
}
@Autowired
public void setDependencyA(@Qualifier("dependencyA") DependencyA dependencyA) {
System.out.println("I am setDependencyA !");
this.dependencyA = dependencyA;
}
public void say() {
this.dependencyA.who();
}
public void who() {
System.out.println("I am dependency B");
}
}
public class CircularDependencyIssue {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(CoolAppConfig.class);
DependencyA dependencyA = applicationContext.getBean(DependencyA.class);
DependencyB dependencyB = applicationContext.getBean(DependencyB.class);
dependencyA.say();
dependencyB.say();
}
}
OUTPUT
I am constructor of Dependency A
I am constructor of Dependency B
I am setDependencyA !
I am setDependencyB !
I am dependency B
I am Dependency A
In the main method I have created an instance of DependencyB
. Now my question is, When we are creating DependencyA
bean first, it will output "I am constructor of Dependency A"
and after resolving the DependencyB
will also output "I am constructor of Dependency B"
.
Now when we are creating the bean of DependencyB
, why the constructor of Dependency B
not called? I mean "I am constructor of Dependency B"
, this should be printed twice in the output, but is present only once.
Does that mean, the beans/objects are shared among dependencyB
and the object created while resolving dependency of dependencyA
?
How does this flow working?
The default Bean scope is Singleton, so only a single spring-managed instance will live for each class.
You could try adding a @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
to one of your instances to see your expected behavior.
For more information, this Baeldung page may be helpful: https://www.baeldung.com/spring-bean-scopes