@primary用于解决同一接口多个实现类导致的注入歧义,通过标注在首选实现类上,使spring在未显式指定时默认注入该bean;它作用于具体实现类而非接口,且同一类型下仅允许一个@primary,优先级低于@qualifier。

接口在 Spring 中本身不能被实例化,真正参与依赖注入的是它的多个实现类。当一个接口有多个 @Service 或 @Component 实现时,Spring 容器无法自动决定该注入哪一个,就会抛出 NoUniqueBeanDefinitionException。@Primary 的作用,就是明确告诉 Spring:“这个实现类是默认首选的”。
为什么接口需要 @Primary?
Spring 的自动装配(@Autowired)按类型匹配 Bean。只要接口类型相同,所有实现类都会被纳入候选池。比如:
-
NotificationService接口有EmailNotificationService和SmsNotificationService两个实现 - 你在 Controller 中写
@Autowired private NotificationService notifier; - Spring 看到两个候选,又没额外指示,就直接报错
@Primary 不是加在接口上,而是加在你希望设为“默认”的那个实现类上——它让这个 Bean 在所有未显式指定的注入点中自动胜出。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
@Primary 的正确用法
只需在目标实现类上添加 @Primary 注解,且确保同一类型下只有一个 @Primary:
- 标注在类上:
@Service @Primary public class EmailNotificationService implements NotificationService { ... } - 不需改接口、不需改注入点,原有
@Autowired保持不变 - 启动时 Spring 会把带
@Primary的 Bean 注册为该类型的“首选” - 其他同类型 Bean 仍存在,只是默认不被选中
@Primary 和 @Qualifier 的关系
两者不是互斥,而是互补:
-
@Primary是全局默认策略:适用于“90% 场景都用这个实现”的情况,减少重复标注 -
@Qualifier是精准控制:当你在某个特定地方需要另一个实现时,可覆盖@Primary,例如:@Autowired @Qualifier("smsNotificationService") private NotificationService smsNotifier; - 优先级上,
@Qualifier高于@Primary,所以后者不会限制灵活性
常见踩坑提醒
实际项目中容易忽略的关键细节:
- 同一类型下出现多个
@Primary,Spring 启动会失败(不允许歧义) - 误把
@Primary加在抽象类或接口上——无效,必须加在具体 Bean 类上 - 配合配置类使用时,
@Bean方法也可加@Primary,效果等同于类上标注 - 第三方 Starter 里可能自带
@Primary的 Bean(如 Spring Boot 自带的RedisTemplate),自定义时要留意是否冲突
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










