Ответ
Критика @Autowired связана с нарушением принципов чистого кода и тестируемости, особенно при полевом внедрении (@Autowired над полем).
Основные проблемы:
- Нарушение принципа инверсии зависимостей (DIP): Класс скрывает свои зависимости, делая их неявными. Невозможно создать экземпляр класса без Spring-контейнера, что усложняет модульное тестирование.
- Сложность тестирования: Для создания объекта в тесте требуется инициализировать Spring-контекст или использовать рефлексию для установки мок-зависимостей.
- Неизменяемость (Immutability): Полевое внедрение делает поля
finalневозможными, снижая безопасность в многопоточных сценариях. - Скрытая связность: Трудно отследить все зависимости класса, что усложняет рефакторинг и понимание кода.
Рекомендуемая альтернатива — внедрение через конструктор:
@Service
public class UserService {
// Зависимость объявлена как final
private final UserRepository userRepository;
// Зависимость явно передается и обязательна
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// ... бизнес-логика
}
Конфигурация в Spring Boot (автоматически):
Начиная с Spring 4.3, для класса с одним конструктором аннотация @Autowired не требуется. Spring использует этот конструктор по умолчанию.
Преимущества конструкторного внедрения:
- Явное объявление зависимостей.
- Возможность создавать
finalполя. - Простое и чистое модульное тестирование (просто
new UserService(mockRepo)). - Гарантирует, что объект создается в полностью инициализированном состоянии.