Ответ
Spring предоставляет три основных способа внедрения зависимостей (DI):
-
Внедрение через конструктор (Constructor Injection) — рекомендуется.
- Почему: Гарантирует неизменяемость зависимостей (final поля), обеспечивает полную инициализацию объекта и упрощает тестирование.
- Как: Аннотация
@Autowiredна конструкторе (необязательна с Spring 4.3 для конструкторов с одним параметром).@Service public class UserService { private final UserRepository repository; // @Autowired // Опционально public UserService(UserRepository repository) { this.repository = repository; } }
-
Внедрение через сеттер (Setter Injection).
- Почему: Позволяет изменять зависимость после создания бина. Подходит для опциональных зависимостей.
- Как: Аннотация
@Autowiredна методе-сеттере.@Service public class OrderService { private PaymentService paymentService; @Autowired public void setPaymentService(PaymentService paymentService) { this.paymentService = paymentService; } }
-
Внедрение через поле (Field Injection) — не рекомендуется.
- Почему: Нарушает инкапсуляцию, усложняет тестирование (требует Spring-контекста или
ReflectionTestUtils), скрывает обязательность зависимости. - Как: Аннотация
@Autowiredнепосредственно на поле.@Service public class ReportService { @Autowired private DataSource dataSource; // Избегайте этого стиля }
- Почему: Нарушает инкапсуляцию, усложняет тестирование (требует Spring-контекста или
Best Practice: Для обязательных зависимостей всегда используйте внедрение через конструктор. Это подход, продвигаемый Spring и сообществом, как наиболее надежный и соответствующий принципам иммутабельности.