Ответ
Внедрение зависимостей через аннотацию @Autowired над полем (field injection) считается антипаттерном по нескольким ключевым причинам:
Недостатки field injection:
- Нарушение инкапсуляции: Делает поля неявно обязательными и изменяемыми, что усложняет поддержку.
- Сложность тестирования: Для юнит-тестов требуется рефлексия или Spring-контекст, чтобы установить мок-зависимость.
- Неявность зависимостей: Класс не сигнализирует о своих зависимостях через публичный API (конструктор/сеттеры).
- Проблемы с final полями: Поля не могут быть
final, что снижает безопасность в многопоточном контексте.
Пример (антипаттерн):
@Service
public class UserService {
@Autowired // Плохо: field injection
private UserRepository userRepository;
}
Рекомендуемый подход — Constructor Injection:
@Service
public class UserService {
private final UserRepository userRepository;
// Зависимости явно объявлены и обязательны
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Преимущества constructor injection:
- Неизменяемость: Поля можно сделать
final. - Явность: Конструктор четко определяет обязательные зависимости.
- Простота тестирования: Легко создать экземпляр класса в тесте, передав моки.
- Безопасность от NPE: Все зависимости гарантированно проинициализированы при создании бина.