Какой механизм Spring Boot реализует принцип «зависимость от абстракций»?

«Какой механизм Spring Boot реализует принцип «зависимость от абстракций»?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Принцип «зависимость от абстракций, а не от реализаций» реализуется в Spring Boot через Dependency Injection (DI), который является частью IoC-контейнера.

Контейнер (ApplicationContext) автоматически связывает конкретные реализации с объявленными зависимостями-интерфейсами, используя аннотации, такие как @Autowired, @Inject или конструктор.

Пример:

// 1. Абстракция (интерфейс)
public interface NotificationService {
    void send(String message);
}

// 2. Конкретная реализация
@Service // Бин регистрируется в контейнере
public class EmailService implements NotificationService {
    @Override
    public void send(String message) {
        System.out.println("Sending email: " + message);
    }
}

// 3. Клиентский код зависит только от абстракции
@RestController
public class ClientController {
    private final NotificationService service; // Зависимость от интерфейса

    @Autowired // Контейнер внедряет реализацию EmailService
    public ClientController(NotificationService service) {
        this.service = service;
    }

    @GetMapping("/notify")
    public String notifyUser() {
        service.send("Hello!");
        return "Notification sent";
    }
}

Это позволяет легко менять реализацию (например, на SmsService), не изменяя код ClientController.