Loading published curriculum…

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

  1. 01Register two implementations of a notification interface.
  2. 02Choose one with @Qualifier and compare the result with a @Primary default.
  3. 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.

  1. 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.
  2. 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.
  3. 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?

Choose one answer

BUILD IT YOURSELF

Register two implementations of a notification interface.

  1. 1.Register two implementations of a notification interface.
  2. 2.Choose one with @Qualifier and compare the result with a @Primary default.
  3. 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.

Go deeper · official references