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.
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 consumedTo 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
