Resolving Multiple Bean Implementations in Spring Boot with @Qualifier and @Primary

This tutorial explains why Spring Boot fails when several beans implement the same interface, and demonstrates how to use @Qualifier to select a specific bean or @Primary to set a default, including code examples, error messages, and best‑practice recommendations.

Java One
Java One
Java One
Resolving Multiple Bean Implementations in Spring Boot with @Qualifier and @Primary

1. Multiple Implementations

When the application defines several Coach beans (e.g., BaseballCoach, CricketCoach, TennisCoach, TrackCoach), Spring cannot decide which one to inject and throws a NoSuchBeanDefinitionException indicating that four beans were found but only one was expected.

Description:
Parameter 0 of constructor in com.greenbook.springbootdemo.rest.FunRestController required a single bean, but 4 were found:
    - baseballCoach: defined in file [/Users/xyz/local/springbootdemo/target/classes/com/greenbook/springbootdemo/service/impl/BaseballCoach.class]
    - cricketCoach: defined in file [/Users/xyz/local/springbootdemo/target/classes/com/greenbook/springbootdemo/service/impl/CricketCoach.class]
    - tennisCoach: defined in file [/Users/xyz/local/springbootdemo/target/classes/com/greenbook/springbootdemo/service/impl/TennisCoach.class]
    - trackCoach: defined in file [/Users/xyz/local/springbootdemo/target/classes/com/greenbook/springbootdemo/service/impl/TrackCoach.class]

This may be due to missing parameter name information

Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

To resolve the ambiguity you can either designate a primary bean, inject a collection of beans, or explicitly qualify the desired bean.

2. Using @Qualifier

The @Qualifier annotation lets you specify the exact bean name to inject, eliminating the ambiguity.

package com.greenbook.springbootdemo.rest;

import com.greenbook.springbootdemo.service.Coach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FunRestController {
    private Coach coach;

    @Autowired
    public FunRestController(@Qualifier("cricketCoach") Coach coach) {
        this.coach = coach;
    }

    @GetMapping("/workout")
    public String getDailyWorkout() {
        return coach.getDailyWorkout();
    }
}

The same approach works for setter injection:

package com.greenbook.springbootdemo.rest;

import com.greenbook.springbootdemo.service.Coach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FunRestController {
    private Coach coach;

    @Autowired
    public void setCoach(@Qualifier("cricketCoach") Coach coach) {
        this.coach = coach;
    }

    @GetMapping("/workout")
    public String getDailyWorkout() {
        return coach.getDailyWorkout();
    }
}

3. Using @Primary

When you want a default bean without qualifying each injection point, annotate one implementation with @Primary. Spring will prefer this bean whenever multiple candidates exist.

package com.greenbook.springbootdemo.service.impl;

import com.greenbook.springbootdemo.service.Coach;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Primary
@Component
public class TrackCoach implements Coach {
    @Override
    public String getDailyWorkout() {
        return "Run a hard 5K!";
    }
}

After marking TrackCoach as primary, the @Qualifier can be removed from the controller, and the application starts successfully.

If more than one bean is annotated with @Primary, Spring throws an error because it cannot determine a unique default:

No qualifying bean of type 'com.greenbook.springbootdemo.service.Coach' available: more than one 'primary' bean found among candidates: [baseballCoach, cricketCoach, tennisCoach, trackCoach]

Therefore, only a single bean should be marked @Primary. In most cases, using @Qualifier is recommended because it has higher precedence than @Primary and avoids accidental conflicts in large projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

qualifierbackend-developmentspring-bootprimarydependency-injection
Java One
Written by

Java One

Sharing common backend development knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.