Ответ
В Spring Framework есть три основных способа внедрения зависимостей, которые могут использоваться аннотацией @Autowired или через Java-конфигурацию.
1. Внедрение через конструктор (Constructor Injection) **
Самый предпочтительный способ. Зависимости передаются через параметры конструктора. Делает класс неизменяемым (immutable), зависимости явные и обязательные.
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired // Необязательно в Spring 4.3+ для единственного конструктора
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
2. Внедрение через сеттер (Setter Injection)
Зависимости устанавливаются через setter-методы. Полезно для опциональных зависимостей или когда нужна возможность их изменения после создания объекта.
@Service
public class PaymentService {
private NotificationService notificationService;
@Autowired
public void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
3. Внедрение через поле (Field Injection) **
Зависимость инжектируется напрямую в поле класса. Не рекомендуется для production-кода, так как скрывает зависимости, усложняет тестирование (требует Spring-контекста или рефлексии) и нарушает принцип инкапсуляции.
@Service
public class OrderService {
@Autowired // Внедрение напрямую в поле
private OrderRepository orderRepository;
}
Рекомендации:
- Используйте Constructor Injection по умолчанию для обязательных зависимостей.
- Setter Injection подходит для опциональных зависимостей или конфигураций, которые могут меняться.
- Избегайте Field Injection в новом коде.
- Внедрение может также настраиваться через Java-based конфигурацию (
@Beanметоды) или XML (в legacy-проектах).