How to use Dependency Injection in Spring
Tags: spring, tutorial, java, backend
Published: 2023-05-02 23:53:10

Hello guys, in this post we'll discuss about Dependency Injection (DI) in Spring framework, first lets talk about whats this means and then how to use in practice, so lets go!


## After all, what means Dependency Injection?


Everyone that starts studying about Spring framework should've listen about the Dependency Injection, but after all what that means? Well, nothing better than going to the source, lets take a look at the documentation of Spring:


> Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern.


Wow, that's a lot! So lets translate this, DI is a principle of software which transfers the control of objects of a program to a container or framework, in this case we put the responsibility in Spring container. So, whats the vantages to use?


> Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.


"Okay okay, but I still don't get the gist of all this, please you could be more clear?" Of course, well our objective is learn to code right? So lets take a look on how this work on code.


Here's how we would create an object dependency in traditional programming:


```java
public class Store {
    private Item item;
 
    public Store() {
        item = new StoreImpl1();    
    }
}
```


In the example above, we need to instantiate an implementation of the Item interface within the Store class itself, that is, our responsibility.


By using DI, we can rewrite the example without specifying the implementation of the Item that we want, in this case the container will provide an implementation for us, that is, Spring's responsibility:


```java
public class Store {
    private Item item;

    public Store(Item item) {
        this.item = item;
    }
}
```


So, I think that now you are more clear about DI, lets take a look on how to use. Basic, Di exists in two ways: **Constructor-based dependency injection** and **Setter-based dependency injection**.


## Constructor-based dependency injection


In the case of constructor-based dependency injection, the container will invoke a constructor with arguments each representing a dependency we want to set. The following example shows a class that can only be dependency-injected with constructor injection:


```java
public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }
}
```


## Setter-based dependency injection


Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean.


```java
public class Car {
    private Engine engine;

    public void setEngine(Engine engine) {
        this.engine = engine;
    }
}
```

So, which way is better? Well, the recommended is that you use constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class.

Furthermore, you should have across in some tutorial, or some code, other type very used for DI, the **Field Injection**, lets take a look on how its implemented:


```java
public class Car {

    @Autowired
    private Engine engine;

    //Constructor, getters, setters...
}
```


This method is discouraged for the Spring team, some reasons for that are: 

- Field injection is easy to use, we intentionally or unintentionally introduce many dependencies, and when injecting too many dependencies means that the class takes on too much responsibility, which violates the object-oriented single responsibility principle, and there is no warning no matter how many are introduced, because this approach can be extended indefinitely.
- Field injection is not unit test friendly, you have to use the Spring IoC container to create these beans (and IoC container strong coupling), but unit testing in principle to be fast, start the IoC container is too slow, if it is construction injection, we can complete the bean as a normal class to create objects, just pass directly through the construction.


## Conclusion


In the end, I hope that you'll have understand about what means Dependency Injection, and the recommended way to use this correctly, obviously the goal of this article doesn't exhaust the subject, but give to you a general comprehension about, you always can learn more read other articles and the [documentation official](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-collaborators).