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

Category : Interview Questions | Sub Category : Spring Boot Interview Questions | By Prasad Bonam Last updated: 2023-08-05 00:29:15 Viewed : 327


Inversion of Control (IoC) and Dependency Injection (DI):

Inversion of Control (IoC) and Dependency Injection (DI) are fundamental design principles in software development that promote loose coupling, flexibility, and modularity. These principles are essential components of the Spring Framework and Spring Boot.

  1. Inversion of Control (IoC): IoC is a design pattern where the control of object creation and management is shifted from the application to a container (framework or container). Instead of creating and managing objects directly, the container creates and injects the objects into the application.

    Example without IoC:

    java
    public class MyApp { public static void main(String[] args) { // Creating objects and managing their dependencies manually MyService myService = new MyService(); MyRepository myRepository = new MyRepository(); myService.setMyRepository(myRepository); } }

    Example with IoC (using Spring):

    java
    @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }

    In the second example, we use Spring Boot to create and manage the MyService and MyRepository beans automatically. The control of object creation and dependency management is now handed over to the Spring container.

  2. Dependency Injection (DI): DI is a specific implementation of IoC, where the dependencies of a class are provided (injected) from outside the class, rather than being created within the class itself. This allows for more flexible and modular code, as classes become less dependent on specific implementations of their dependencies.

    Example without DI:

    java
    public class MyService { private MyRepository myRepository; public MyService() { myRepository = new MyRepository(); // Dependency is tightly coupled with the class } }

    Example with DI (using Spring):

    java
    @Service public class MyService { private MyRepository myRepository; @Autowired public MyService(MyRepository myRepository) { this.myRepository = myRepository; // Dependency is injected from outside } }

    In the second example, the MyRepository dependency is provided by the Spring container through constructor injection. The class is no longer responsible for creating its dependency, making it more flexible and decoupled from specific implementations of MyRepository.

By applying IoC and DI principles, developers can write code that is easier to maintain, test, and extend. It also allows for better separation of concerns and promotes the use of interfaces, making the code more modular and adaptable to change. The Spring Framework and Spring Boot are built on these principles, making them popular choices for developing robust and scalable applications.

Lets go through examples of the Inversion of Control (IoC) and Dependency Injection (DI) principles to understand them better.

  1. Inversion of Control (IoC): The Inversion of Control principle states that the control of object creation and management should be shifted from the application code to an external container or framework. In other words, the flow of control is inverted, and the framework is responsible for creating and managing objects (beans) instead of the application.

    Example - Without IoC:

    java
    public class MyApp { public static void main(String[] args) { MyService myService = new MyService(); myService.doSomething(); } } public class MyService { public void doSomething() { // Business logic here... } }

    In this example, the MyApp class directly creates an instance of MyService, tightly coupling them together. This creates a dependency on MyService, making it difficult to change or test MyApp.

    Example - With IoC:

    java
    @Service public class MyService { public void doSomething() { // Business logic here... } } @SpringBootApplication public class MyApp { private final MyService myService; @Autowired public MyApp(MyService myService) { this.myService = myService; } public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }

    In this example, the MyApp class depends on the MyService interface, and the Spring IoC container is responsible for creating and injecting the instance of MyService into MyApp. This removes the tight coupling between classes, making the application more maintainable and testable.

  2. Dependency Injection (DI): Dependency Injection is a specific implementation of the IoC principle. It refers to the process of supplying a dependent object (or a dependency) to a class rather than the class creating the dependency itself.

    Example - Without DI:

    java
    public class MyService { private MyRepository myRepository; public MyService() { myRepository = new MyRepository(); } public void doSomething() { myRepository.saveData(); } } public class MyRepository { public void saveData() { // Logic to save data to the database } }

    In this example, MyService creates an instance of MyRepository within its constructor, making it difficult to replace or mock MyRepository for testing purposes.

    Example - With DI:

    java
    @Service public class MyService { private final MyRepository myRepository; @Autowired public MyService(MyRepository myRepository) { this.myRepository = myRepository; } public void doSomething() { myRepository.saveData(); } } @Repository public class MyRepository { public void saveData() { // Logic to save data to the database } }

    In this example, MyService depends on the MyRepository interface, and the dependency is injected through constructor injection using the @Autowired annotation. The Spring IoC container resolves the dependency and provides an instance of MyRepository to MyService. This allows better decoupling and easier testing.

By using the principles of IoC and DI, Spring Boot makes it easier to develop and maintain applications. It promotes loose coupling, testability, and modularity, as the framework takes care of managing dependencies and object creation, allowing developers to focus on writing business logic.

Search
Related Articles

Leave a Comment: