Как разрешить неоднозначность при внедрении бинов с помощью @Primary в Spring?

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

Ответ

Аннотация @Primary указывает Spring, какой бин следует предпочесть по умолчанию, когда несколько бинов одного типа (интерфейса) подходят для внедрения через @Autowired. Это решает проблему NoUniqueBeanDefinitionException.

Пример с неоднозначностью:

public interface PaymentService {
    void pay();
}

@Component("cardPayment") // Бин 1
public class CardPaymentService implements PaymentService { ... }

@Component("cashPayment") // Бин 2
public class CashPaymentService implements PaymentService { ... }

@Service
public class ShopService {
    @Autowired // ОШИБКА: NoUniqueBeanDefinitionException - 2 бина типа PaymentService
    private PaymentService paymentService;
}

Решение с @Primary:

@Component
@Primary // Этот бин будет выбран по умолчанию
public class CardPaymentService implements PaymentService { ... }

@Component
public class CashPaymentService implements PaymentService { ... }

@Service
public class ShopService {
    @Autowired // Будет внедрён CardPaymentService
    private PaymentService defaultPaymentService;
}

Альтернатива — @Qualifier: Для точного выбора конкретного бина используйте @Qualifier("beanName").

@Autowired
@Qualifier("cashPayment") // Явно указываем бин
private PaymentService paymentService;

@Primary задаёт поведение по умолчанию, @Qualifier — точное указание.