Spring Boot Interview Questions

25 Questions
Spring Boot

Spring Boot

Java

Java

BackendWeb Development

Question 8

What is dependency injection, and how does Spring Boot support it?

Answer:

Dependency Injection (DI) is a design pattern used to implement Inversion of Control (IoC), allowing the creation and management of dependencies outside of the dependent objects. It decouples the creation of objects and their dependencies from the business logic, making code more modular, testable, and maintainable.

Key Concepts of Dependency Injection

  1. Inversion of Control (IoC): The control of object creation and dependency management is inverted from the dependent object itself to an external framework or container.
  2. Dependency: An object that another object requires to function.
  3. Injection: The process of passing (injecting) the dependencies into the dependent object.

Types of Dependency Injection

  1. Constructor Injection: Dependencies are provided through the class constructor.
  2. Setter Injection: Dependencies are provided through setter methods.
  3. Field Injection: Dependencies are directly assigned to fields (less common due to visibility and testability concerns).

How Spring Boot Supports Dependency Injection

Spring Boot, built on the Spring Framework, provides comprehensive support for dependency injection through its IoC container. Here are the main ways Spring Boot supports DI:

  1. Annotation-Based Configuration:

    • @Component: Indicates that a class is a Spring-managed component.
    • @Autowired: Marks a constructor, field, or setter method to be injected with a dependency.
    • @Service, @Repository, @Controller: Specialized annotations for specific types of components.
  2. Java-Based Configuration:

    • @Configuration: Indicates that a class contains bean definitions.
    • @Bean: Declares a bean within a @Configuration class.
  3. XML-Based Configuration (Less common in Spring Boot):

    • Beans can be defined and wired together using XML configuration files.

Example: Dependency Injection in Spring Boot

Step 1: Define Components

Define service and repository components using @Service and @Repository annotations.

import org.springframework.stereotype.Service;

@Service
public class MyService {

    private final MyRepository myRepository;

    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    public String performService() {
        return myRepository.getData();
    }
}
import org.springframework.stereotype.Repository;

@Repository
public class MyRepository {

    public String getData() {
        return "Hello from MyRepository";
    }
}

Step 2: Autowire Dependencies

Spring Boot will automatically wire the dependencies by scanning for components and injecting them where required.

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.beans.factory.annotation.Autowired;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    private final MyService myService;

    @Autowired
    public DemoApplication(MyService myService) {
        this.myService = myService;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println(myService.performService());
    }
}

In this example:

  • MyService depends on MyRepository.
  • The @Autowired annotation is used to inject MyRepository into MyService.
  • The DemoApplication class, annotated with @SpringBootApplication, autowires MyService and uses it in the run method.

Constructor Injection vs. Field Injection

Constructor Injection is generally preferred because:

  • It makes dependencies explicit and ensures that the object is fully initialized with all required dependencies.
  • It facilitates easier testing by allowing dependencies to be injected through the constructor.
  • It helps in creating immutable objects.

Field Injection can be simpler but has some downsides:

  • It hides dependencies from the object's API, making it less clear what the object depends on.
  • It can lead to issues with immutability and testing.

Example: Constructor Injection

@Service
public class MyService {

    private final MyRepository myRepository;

    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    public String performService() {
        return myRepository.getData();
    }
}

Example: Field Injection

@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    public String performService() {
        return myRepository.getData();
    }
}

Using @Configuration and @Bean

You can also define beans explicitly using Java-based configuration.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyService(myRepository());
    }

    @Bean
    public MyRepository myRepository() {
        return new MyRepository();
    }
}

Summary

  • Dependency Injection (DI): A design pattern that provides dependencies to objects from an external source.
  • Spring Boot Support:
    • Annotation-Based: @Component, @Service, @Repository, @Autowired.
    • Java-Based Configuration: @Configuration and @Bean.
  • Constructor Injection: Preferred for its clarity, immutability, and testability.
  • Field Injection: Simpler but less explicit and harder to test.
  • Configuration and Bean Definition: Allows explicit bean definitions and wiring using configuration classes.

Spring Boot’s support for dependency injection simplifies the development of loosely-coupled, maintainable, and testable applications by managing the lifecycle and dependencies of beans in the application context.

Recent job openings