App Development

Inversion of Control(IoC) and Dependency injection(DI)

In Spring framework, the core container module provides the essential functionality. The BeanFactory is a primary component of the core container and the Inversion of Control (IoC) pattern is applied by BeanFactory. IoC is used to separate an application’s configuration and dependency specification from the actual application code and it is achieved by Dependency Injection. 

What are Inversion of Control (IoC) and Dependency injection (DI)?

Inversion of Control(IoC) is also known as Dependency injection (DI). The Spring container uses Dependency Injection (DI) to manage the components that build up an application and these objects are called Spring Beans. Spring implements DI by either an XML configuration file or annotations. The Container is responsible for managing the object lifecycle (create the objects, wire them together, configure them, and manage their complete lifecycle from creation till destruction). The main goal of the Inversion of control and Dependency Injection is to remove dependencies of an application. This makes the system more decoupled and maintainable.

Inversion of Control(IoC) is a Software Design Pattern and is implemented in several ways (events, delegates etc). Dependency injection (DI) is a subtype of Inversion of Control(IoC) and is implemented by constructor injection, setter injection or method injection and it deals with how components get hold of their dependencies

Inversion of Control(IoC) is a principle by which the control of objects is transferred to a container or framework. Dependency injection is a pattern through which IoC is implemented and the act of connecting objects with other objects or injecting objects into objects is done by container rather than by the object themselves.

In Inversion of Control(IoC), instead of an application calling the framework – it is the framework that calls the components specified by the application. IoC is also known as dependency injection (DI).

Spring framework mainly supports two forms of Dependency Injection:

  • Constructor Injection: The container will invoke the constructor with arguments each representing a dependency that we want to set i.e, all the dependencies are declared in one step. This helps in understanding whether the class depends on too many services. Constructor injection is the best practice to inject dependencies.
  • Setter Injection: The container will call the setter methods of our class. The objects of the class will have setters. The Inversion of Control(IoC) container will use these setters to provide the resource at run-time after invoking a no-argument constructor or no-argument static factory method to instantiate their bean. Setter injection is used for optional dependencies.

  Wiring allows the Spring container to automatically resolve dependencies between collaborating beans by inspecting the beans that have been defined. we can inject the dependencies by making them with @Autowired annotation which is called field-based dependency injection.

Public class Company{
  @Autowired
  Private Employee employee; 
 }                                         

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 Company{
  @Autowired
  @Qualifier("emp1")
  Private Employee employee;
 }

Why Inversion of Control(IoC) and Dependency injection (DI)?

Scenario: For instance, we have a class Company and it has a dependency on class Employee.

Solution without Spring IoC: The Company class configures itself so it will set the value of this Employee fields within the same class only.
   

class Company{
  Employee employee;
  Company(){                                             
  employee=newEmployee(“111”,”ABC”);
  }
}

Solution with Spring IoC: By using Spring IoC, it is done in one of two ways.

  • Constructor Injection: The container will invoke the constructor with arguments each representing a dependency that we want to set.
class Company{
   Employee employee;
   Company(Employee employee){
   this.employee=employee;
   }
 }

  • Setter Injection: The container will call the setter methods of our class and the IoC container will use these setters to provide the resource at run-time.
 class Company{
  Employee employee;
  Public void setEmployee(Employee employee){
  this.employee=employee;
  }
}

 Real-time Scenario:

         Dependency Injection (DI) provides objects that an object needs. So rather than the dependencies construct themselves they are injected by some external means. For instance, we have a class called “Customer” who uses a “Logger” class to log errors. So rather than creating the “Logger” from within the class, we can inject the same via a constructor as shown below.

class Customer{
  Logger log;
  Customer(Logger  errorlog){
  log=errorlog;
 }
}

The biggest benefit achieved by the above approach is “Decoupling”. We can invoke the customer object and pass any kind of “Logger” object.

Advantages:

  • Helps to enable loose coupling architecture, there is no need to modify the code if our logic is moved to a new environment.
  • Makes Unit testing easy.
  • Boilerplate code is reduced, as initializing of dependencies is done by the injector component.
  • Extending the application becomes easier.
  • Allows code to be more reusable, testable, and readable.
  • Reduce unnecessary dependencies.
  • Allows concurrent or independent development.
  • Reduced module complexity
  • Increased system maintainability, because logic changes in the domain affect fewer modules.
  • Increased module reusability.

Conclusion:

As mentioned above, Spring Inversion of Control(IoC) helps in the creation of loosely coupled applications because of Dependency Injection. By implementing Inversion of Control, a software/object consumer get more controls/options over the software/objects, instead of being controlled or having fewer options.