Какие есть способы внедрения зависимостей с помощью @Autowired в Spring и какой из них предпочтителен?

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

Ответ

В Spring аннотацию @Autowired можно использовать для инжекции зависимостей тремя основными способами. Рекомендации основаны на тестируемости, безопасности и best practices.

1. Через конструктор (Рекомендуемый способ)

Почему: Позволяет объявить поля как final, обеспечивая неизменяемость и безопасную инициализацию. Упрощает модульное тестирование (можно передать моки напрямую). Явно показывает обязательные зависимости.

@Service
public class UserService {
    private final UserRepository repository;

    @Autowired // Необязателен в Spring 4.3+, если конструктор один
    public UserService(UserRepository repository) {
        this.repository = repository;
    }
}

2. Через поле (Field Injection)

Почему: Лаконичный синтаксис, но имеет недостатки. Усложняет тестирование (требует Spring Context или рефлексии для установки поля). Не позволяет сделать поле final.

@Service
public class UserService {
    @Autowired
    private UserRepository repository;
}

3. Через сеттер (Setter Injection)

Почему: Подходит для опциональных или изменяемых зависимостей. Сохраняет возможность изменения зависимости после создания бина.

@Service
public class UserService {
    private UserRepository repository;

    @Autowired
    public void setRepository(UserRepository repository) {
        this.repository = repository;
    }
}

Вывод: Инжекция через конструктор — лучшая практика для обязательных зависимостей. Она способствует написанию чистого, тестируемого и безопасного кода.