Что произойдет при инъекции интерфейса с двумя реализациями через @Autowired в Spring?

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

Ответ

Spring выбросит NoUniqueBeanDefinitionException, так как не сможет определить, какую реализацию использовать.

Пример проблемы:

public interface PaymentService {
    void processPayment();
}

@Component
class CreditCardService implements PaymentService { /* ... */ }

@Component
class PayPalService implements PaymentService { /* ... */ }

@Service
class OrderService {
    @Autowired
    private PaymentService paymentService; // ОШИБКА: 2 бина реализуют интерфейс
}

Способы разрешения неоднозначности:

  1. @Qualifier (явное указание):
    
    @Component("creditCard")
    class CreditCardService implements PaymentService { /* ... */ }

@Component("paypal") class PayPalService implements PaymentService { / ... / }

@Autowired @Qualifier("creditCard") private PaymentService paymentService;


2. **@Primary** (бин по умолчанию):
```java
@Component
@Primary // Выбирается при отсутствии @Qualifier
class CreditCardService implements PaymentService { /* ... */ }

@Component
class PayPalService implements PaymentService { /* ... */ }
  1. @Resource с именем бина:

    @Resource(name = "creditCardService")
    private PaymentService paymentService;
  2. Инъекция всех реализаций (List/Map):

    
    @Autowired
    private List<PaymentService> allPaymentServices;

@Autowired private Map<String, PaymentService> paymentServicesMap; // Ключи: имена бинов (creditCardService, payPalService)


5. **Конфигурация через @Bean:**
```java
@Configuration
class AppConfig {
    @Bean
    public PaymentService paymentService() {
        return new CreditCardService(); // явный выбор
    }
}