Какой способ внедрения зависимости в Spring лучше всего подходит для обеспечения иммутабельности?

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

Ответ

Для обеспечения иммутабельности (неизменяемости) зависимостей предпочтительным и рекомендуемым способом является внедрение через конструктор (Constructor Injection).

Причины:

  1. Гарантия однократной инициализации: Зависимость инжектируется один раз при создании бина, после чего ссылка на неё не может быть изменена.
  2. Использование final полей: Поля зависимостей можно объявить как final, что обеспечивает потокобезопасность и явно выражает намерение.
  3. Обязательность зависимостей: Конструктор явно требует передачи всех необходимых зависимостей для корректной работы объекта.

Пример:

import org.springframework.stereotype.Service;

@Service
public class OrderService {
    // Поле объявлено как final, его нельзя изменить после инициализации
    private final PaymentProcessor paymentProcessor;
    private final NotificationService notificationService;

    // Внедрение зависимостей через конструктор (Spring сделает это автоматически)
    public OrderService(PaymentProcessor paymentProcessor, 
                        NotificationService notificationService) {
        this.paymentProcessor = paymentProcessor;
        this.notificationService = notificationService;
    }

    public void processOrder(Order order) {
        paymentProcessor.charge(order);
        notificationService.sendConfirmation(order);
    }
}

Сравнение с другими способами:

  • Setter Injection: Позволяет изменять зависимость после создания объекта, что нарушает иммутабельность.
  • Field Injection: Скрывает обязательность зависимостей, усложняет тестирование и не поддерживает final поля.