How does Spring resolve autowiring ambiguity with @Qualifier and @Primary?
Quick Answer
When multiple beans of the same type exist, Spring's default by-type autowiring is ambiguous and fails at startup with a NoUniqueBeanDefinitionException unless disambiguated. @Primary marks one candidate bean as the default choice whenever multiple matches exist. @Qualifier lets the injection point specify exactly which named bean it wants, overriding @Primary when both are present at a given injection site.
Detailed Answer
Spring's default autowiring strategy resolves a dependency by type first. If more than one bean of that type exists, autowiring becomes ambiguous:
interface PaymentGateway { }
@Component class StripeGateway implements PaymentGateway { }
@Component class PayPalGateway implements PaymentGateway { }
@Service
class OrderService {
@Autowired
PaymentGateway gateway; // ambiguous! Two candidates — NoUniqueBeanDefinitionException at startup
}
@Primary designates one candidate as the default to use whenever multiple beans of a type match and no more specific instruction is given:
@Component
@Primary
class StripeGateway implements PaymentGateway { } // chosen by default among the candidates
@Qualifier lets a specific injection point name exactly which bean it wants, by bean name (or a custom qualifier value):
@Service
class OrderService {
private final PaymentGateway gateway;
OrderService(@Qualifier("payPalGateway") PaymentGateway gateway) {
this.gateway = gateway; // explicitly requests the PayPal bean, regardless of @Primary
}
}
Precedence: an explicit @Qualifier at the injection site always wins over @Primary — @Primary only matters when the injection point gives no more specific instruction. This lets you set a sensible application-wide default with @Primary while still allowing specific call sites to opt into a different implementation via @Qualifier where needed.
@Qualifier can also be used with a custom annotation (@Qualifier as a meta-annotation on your own annotation type) for more expressive, type-safe disambiguation than raw string bean names.