javaspringdependency-injectionannotationsioc-container

Does getbean() method share the beans for different instances of the bean?


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?


Solution

  • 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