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.