Dependency Injection in Spring Boot

Dependency Injection in Spring can be done through constructors, setters or fields.

Constructor-Based Dependency Injection

@Configuration
public class AppConfig {

    @Bean
    public Item item1() {
        return new ItemImpl1();
    }

    @Bean
    public Store store() {
        return new Store(item1());
    }
}

The @Configuration annotation indicates that the class is a source of bean definitions. We can also add it to multiple configuration classes.

We use the @Bean annotation on a method to define a bean. If we don’t specify a custom name, then the bean name will default to the method name.

For a bean with the default singleton scope, Spring first checks if a cached instance of the bean already exists, and only creates a new one if it doesn’t. If we’re using the prototype scope, the container returns a new bean instance for each method call.

Setter-Based Dependency Injection

@Bean
public Store store() {
    Store store = new Store();
    store.setItem(item1());
    return store;
}

Field-Based Dependency Injection

public class Store {
    @Autowired
    private Item item; 
}

While constructing the Store object, if there’s no constructor or setter method to inject the Item bean, the container will use reflection to inject Item into Store.

Autowiring Dependencies

Wiring allows the Spring container to automatically resolve dependencies between collaborating beans by inspecting the beans that have been defined.

There are four modes of autowiring a bean using an XML configuration:

no: the default value – this means no autowiring is used for the bean and we have to explicitly name the dependencies.
byName: autowiring is done based on the name of the property, therefore Spring will look for a bean with the same name as the property that needs to be set.
byType: similar to the byName autowiring, only based on the type of the property. This means Spring will look for a bean with the same type of the property to set. If there’s more than one bean of that type, the framework throws an exception.
constructor: autowiring is done based on constructor arguments, meaning Spring will look for beans with the same type as the constructor arguments.

For example, let’s autowire the item1 bean defined above by type into the store bean:

@Bean(autowire = Autowire.BY_TYPE)
public class Store {
    
    private Item item;

    public setItem(Item item){
        this.item = item;    
    }
}

We can also inject beans using the @Autowired annotation for autowiring by type:

public class Store {
    
    @Autowired
    private Item item;
}

If there’s more than one bean of the same type, we can use the @Qualifier annotation to reference a bean by name:

public class Store {
    
    @Autowired
    @Qualifier("item1")
    private Item item;
}

References
https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring