What is Dependency Injection (DI) in Spring?

Dependency injection (DI) is a design pattern that promotes loose coupling between classes by injecting dependencies from outside the class. In other terms, Dependency Injection is a process of injecting dependent bean objects into target objects. 

Dependency Injection is the main functionality provided by Spring IOC(Inversion of Control).  

Dependency Injection reduces coupling between multiple objects as the framework dynamically injects it. Spring IoC Container uses DI to inject one object into another object. 

Advantages of Dependency Injection:

  • Highly Extensible Code
    • Since dependencies are injected externally the programmer can focus more on scaling up the application instead of manually managing the dependencies.
  • Testable Code
    • Programmers can create test cases more easily by using mock databases with dependency injection.
  • Reusable Code
    • We can reuse the logic and implementation of the codes.
  • Maintainable Code
    • Since our code is loosely coupled it provides high-maintenance to the code.

Types of Dependency Injection:

We have three different types of dependency injections we can refer to the demo dependency injection spring boot project from here…

  1. Constructor Dependency Injection
  • Constructor Dependency injection is an injection type where a class constructor provides dependencies. Constructor injection guarantees the ready-to-use state of the class.
  • Following is the example for constructor dependency injection.
  • Before Spring 4.3, we had to add an @Autowired annotation to the constructor. With the newer version of Spring, this is optional if the class has only one constructor.
  • When we have a class with multiple constructors, we need to explicitly add the @Autowired annotation to any of the constructors so that Spring knows which constructor to use to inject the dependencies.
  • Constructor dependency injection is best in Spring as it has better readability, supports immutability, and is state-safe(the object is instantiated to the entire state or not at all).
  1. Setter Dependency Injection
  • Setter injection uses the setter method to inject dependency on any Spring-managed bean.
  • We have to annotate the setter method with the @Autowired annotation.
  • The call first goes to the no-argument constructor and then to the setter method. It does not create any new bean instances.
  • Following is the example of setter dependency injection. We have a utility class whose reference is injected by setter injection.
  1. Field Dependency Injection
  • As the name says, the dependency is injected directly into the field, with no constructor or setter needed. This is done by annotating the class member with the @Autowired annotation.
  • Spring container uses reflection to inject the dependencies, which is costlier than constructor-based or setter-based injection.

Following is the Utility class with @Component annotation.

When to Use?

  1. Constructor Dependency Injection
    • Constructor Injection is always the first choice when it comes to Dependency Injection because of its reliable and strict nature.
    • We can use Constructor Injection when an Object must be created with all of its dependencies.
    • Constructors are more suitable for mandatory dependencies and when aiming for immutability.
    • With constructor injection, it’s possible to detect circular dependencies at compile time since they would create unresolvable errors.
  2. Setter Dependency Injection
    • We can use setter injection when many dependencies are or we need readability.
  3. Field Injection
    • Field Injection can also be used in scenarios where Constructor Injection is not possible (and Circular Dependencies have to be avoided even as a workaround).

Drawbacks of:

  1. Constructor Dependency Injection
    • Though constructor injection is the best practice to use it also has some drawbacks. For instance, it can lead to a large number of parameters in the constructor, which can make the code cluttered and hard to maintain.
    • It can also make the testing more difficult, as you need to provide mock or stub objects for all the dependencies.
  2. Setter Dependency Injection
    • One of the main disadvantages of setter-based injection is that it can lead to objects in an inconsistent state if all required dependencies are not established.
    • This can be problematic because the object may not function correctly if methods are used before all dependencies have been established.
  3. Field Dependency Injection
    • Field injection creates a risk of NullPointerException if dependencies aren’t correctly initialized.
    • Using the field injection, we are unable to create immutable classes.
    • The use of field injection can result in circular dependencies going unnoticed.

-A blog by Shwetali Khambe

Related Posts