Mastering Spring Boot Bean Selection: 6 Ways to Choose the Right Implementation
This tutorial walks through six practical techniques—@Qualifier, @Primary, @Profile, collection injection, @Priority, and custom @Conditional—to control which implementation of a Spring Boot interface is autowired, complete with code examples and usage tips.
In this article we explore how to select the correct implementation class for injection when an interface has multiple implementations in Spring Boot.
When Spring cannot decide which bean to inject, it throws the error “required a single bean but found X”, indicating ambiguity.
1. Use @Qualifier
Assign a custom qualifier name to a bean and reference it during injection.
<code>@Repository
@Qualifier("mysqlDAO-1")
public class MySQLDAO implements DAO<User> {}
@Repository
public class OracleDAO implements DAO<User> {}
@Component
public class CompDAO {
private final DAO dao1;
private final DAO dao2;
public CompDAO(@Qualifier("mysqlDAO-1") DAO dao1, DAO oracleDAO) {
this.dao1 = dao1;
this.dao2 = oracleDAO;
}
}
</code>2. Use @Primary
Mark one implementation as primary so Spring picks it when no qualifier is specified.
<code>@Repository
@Primary
public class OracleDAO implements DAO<User> {}
</code>If other implementations are needed, retrieve them manually via ApplicationContext#getBean .
3. Use @Profile
Activate beans only under specific Spring profiles (e.g., dev or prod ).
<code>@Repository
@Profile("dev")
public class MySQLDAO implements DAO<User> {}
@Repository
@Profile("prod")
public class OracleDAO implements DAO<User> {}
</code>The active profile is controlled by the spring.profiles.active property.
4. Inject All Implementations into a Collection
Spring can inject all beans of a type into a List , Set , Map , or array.
<code>@Component
public class CompDAO {
private final List<DAO> daos;
public CompDAO(List<DAO> daos) { this.daos = daos; }
}
</code> <code>@Component
public class CompDAO {
private final Map<String, DAO> daos;
public CompDAO(Map<String, DAO> daos) { this.daos = daos; }
public void use() {
MySQLDAO mdao = (MySQLDAO) this.daos.get("mySQLDAO");
OracleDAO odao = (OracleDAO) this.daos.get("oracleDAO");
// TODO
}
}
</code>When using a Map , Spring ignores @Qualifier and profile annotations for beans that do not match the current profile.
5. Use @Priority
Assign an integer priority (lower value = higher priority) to beans; the highest‑priority bean is chosen for injection.
<code>@Repository
@Priority(2)
public class OracleDAO implements DAO<Date> {}
@Repository
@Priority(1)
public class MySQLDAO implements DAO<Date> {}
</code>In this example, MySQLDAO will be injected because it has the smallest priority value.
6. Custom @Conditional
Create a class implementing Condition and use @Conditional to activate a bean only when custom logic returns true.
<code>public class PackCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return "mysql".equalsIgnoreCase(context.getEnvironment().getProperty("pack.active"));
}
}
</code> <code>@Repository
@Conditional(PackCondition.class)
public class MySQLDAO implements DAO<User> {}
</code>Only when the property pack.active is set to mysql will MySQLDAO be created.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.