junior
Для чего нужны @Qualifier и @Primary?
@Qualifier и @Primary решают проблему неоднозначности, когда в контейнере есть несколько бинов одного типа.
@Qualifier – указывает конкретное имя бина для внедрения. @Primary – помечает бин как «предпочтительный» по умолчанию. Приоритет: @Qualifier > @Primary > совпадение по имени > ошибка.
Пример использования @Qualifier и @Primary
public interface NotificationService {
void send(String message);
}
@Service("emailNotification")
@Primary // будет внедряться по умолчанию
public class EmailNotificationService implements NotificationService {
public void send(String message) { /* отправка email */ }
}
@Service("smsNotification")
public class SmsNotificationService implements NotificationService {
public void send(String message) { /* отправка SMS */ }
}
@Service
public class OrderService {
// Внедрится EmailNotificationService, т.к. он @Primary
public OrderService(NotificationService notificationService) { }
}
@Service
public class AlertService {
// Явно выбираем SMS, несмотря на @Primary
public AlertService(@Qualifier("smsNotification") NotificationService notificationService) { }
}
Внедрение всех реализаций
Пример
@Service
public class NotificationManager {
private final List<NotificationService> services;
// Spring внедрит ВСЕ бины типа NotificationService
public NotificationManager(List<NotificationService> services) {
this.services = services;
}
}
Собственный квалификатор (лучшая практика)
Пример
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface Email { }
@Service
@Email
public class EmailNotificationService implements NotificationService { }
// Использование -- проверяется на этапе компиляции:
public OrderService(@Email NotificationService notificationService) { }
На собеседовании: важно знать приоритет разрешения и когда использовать что. Частая ошибка – использовать строковые значения в
@Qualifierвместо собственных аннотаций-квалификаторов (строки не проверяются при компиляции).