How can we handle multiple beans of the same type?

When multiple beans of the same type exist in the Spring container, Spring cannot determine which bean should be injected automatically and throws a NoUniqueBeanDefinitionException. Spring provides several mechanisms to explicitly specify which bean should be used.

Key Points: • @Qualifier is used to select a specific bean by name. • @Primary marks one bean as the default choice for dependency injection. • Collections such as List or Map can be used to inject all beans of a particular type.

Example: Suppose an application supports multiple payment methods:

• Credit Card Payment • PayPal Payment • UPI Payment

All of them implement the same PaymentService interface. Spring needs additional information to determine which implementation should be injected.

Code Example:

@Service
@Qualifier("creditCardPayment")
public class CreditCardPaymentService
        implements PaymentService {
}

@Service
@Qualifier("paypalPayment")
public class PaypalPaymentService
        implements PaymentService {
}

@Service
public class OrderService {

    private final PaymentService paymentService;

    public OrderService(
            @Qualifier("creditCardPayment")
            PaymentService paymentService) {

        this.paymentService = paymentService;
    }
}

Using @Primary:

@Service
@Primary
public class CreditCardPaymentService
        implements PaymentService {
}

In this case, Spring automatically injects CreditCardPaymentService whenever PaymentService is required unless another bean is explicitly selected using @Qualifier.

Injecting All Implementations:

@Autowired
private List<PaymentService> paymentServices;

Spring injects all available PaymentService implementations into the list.

Similarly:

@Autowired
private Map<String, PaymentService> paymentServices;

The map key represents the bean name and the value represents the bean instance.

Common Approaches:

1. @Qualifier • Explicit bean selection. • Best when a specific implementation is required.

2. @Primary • Defines the default bean. • Reduces the need for multiple qualifiers.

3. Collection Injection • Injects all implementations. • Useful for plugin-based or strategy-based designs.

Real-World Example:

Notification Service Interface:

• EmailNotificationService • SmsNotificationService • PushNotificationService

A NotificationManager can inject all implementations and choose the appropriate one dynamically at runtime.

Common Exception:

NoUniqueBeanDefinitionException

This occurs when: • Multiple beans of the same type exist. • Spring cannot determine which bean should be injected.

Best Practice: • Use @Primary for the default implementation. • Use @Qualifier for explicit bean selection. • Prefer constructor injection over field injection.

Interview Tip: A concise interview answer is: When multiple beans of the same type exist, Spring resolves the conflict using @Qualifier to specify the required bean or @Primary to mark a default bean. If all implementations are needed, Spring can inject them as a List or Map of beans.