09 · Spring Framework and the IoC container / LESSON 40 OF 102
Bean ambiguity, @Qualifier, and @Primary
When multiple beans satisfy one type, make the intended choice explicit.
Before this lesson: Constructor injection, optional dependencies, and cycles
Understand the topic
@Primary provides a preferred candidate for single-valued injection. @Qualifier narrows candidates using a qualifier value. Injecting a collection intentionally requests all matching beans and should not depend on an accidental registration order.
Use a domain-relevant qualifier such as transactionalMail rather than coupling business code to an implementation class name. Repeated ambiguity can also indicate that one interface combines unrelated responsibilities.
EXAMPLE · JAVA
ClockConfig.java
import java.time.Clock;
import org.springframework.context.annotation.*;
@Configuration
public class ClockConfig {
@Bean @Primary Clock systemClock() { return Clock.systemUTC(); }
@Bean("fixedClock") Clock fixedClock() {
return Clock.fixed(java.time.Instant.EPOCH, java.time.ZoneOffset.UTC);
}
}What to expect
Unqualified Clock injection selects systemClock; @Qualifier("fixedClock") selects the fixed test clock.
YOUR TURN
Put it into practice
- 01Register two implementations of a notification interface.
- 02Choose one with @Qualifier and compare the result with a @Primary default.
- 03Verify: A test proves each injection point receives its intended implementation.
Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.
UNDER THE HOOD
Build the mental model
When multiple beans satisfy one type, make the intended choice explicit.
- 01@Primary provides a preferred candidate for single-valued injection. @Qualifier narrows candidates using a qualifier value. Injecting a collection intentionally requests all matching beans and should not depend on an accidental registration order.
- 02Use a domain-relevant qualifier such as transactionalMail rather than coupling business code to an implementation class name. Repeated ambiguity can also indicate that one interface combines unrelated responsibilities.
- 03Trace the example: Unqualified Clock injection selects systemClock; @Qualifier("fixedClock") selects the fixed test clock.
A mistake worth avoiding
NoUniqueBeanDefinitionException appears after adding a second adapter.
DEBUGGING ROOM
Something broke. Where do you look?
NoUniqueBeanDefinitionException appears after adding a second adapter.
Before revealing the diagnosis, write down your first investigation step.
CHECK YOUR UNDERSTANDING
Does @Primary delete other matching beans?
BUILD IT YOURSELF
Register two implementations of a notification interface.
- 1.Register two implementations of a notification interface.
- 2.Choose one with @Qualifier and compare the result with a @Primary default.
- 3.Reproduce this failure, then repair it: NoUniqueBeanDefinitionException appears after adding a second adapter.
Acceptance checklist
Lab completion is your self-report. Knowledge checks do not certify project quality.
RETRIEVE IT FROM MEMORY
Does @Primary delete other matching beans?
Revisit this lesson in three days after a successful check or lab.
Ready for the next step?
A test proves each injection point receives its intended implementation.
Reading is separate from passing a knowledge check or completing a lab.