当前位置: 首页 > news >正文

深入理解 Spring 中的 @Primary 与 @Qualifier

一、背景

在 Spring / Spring Boot 项目中,经常会遇到同一个接口有多个实现类的情况。例如:

  • Mysql 实现

  • MongoDB 实现

  • Redis 实现

当使用@Autowired注入时,Spring 默认是按类型注入(By Type)

如果容器中存在多个同类型 Bean,就会出现:

NoUniqueBeanDefinitionException

为了解决这个问题,Spring 提供了两个核心注解:

  • @Primary

  • @Qualifier

本文将系统讲解它们的作用、优先级以及实际项目中的最佳实践,并提供一个可运行的 Spring Boot 示例项目


二、@Primary 注解

1. 作用

@Primary用来指定默认 Bean

当存在多个相同类型 Bean 时,如果某个 Bean 标记为@Primary,Spring 在自动注入时会优先选择它。

2. 示例

@Component @Primary public class MysqlMessageService implements MessageService { @Override public String send() { return "Message from MySQL service"; } }
@Component public class EmailMessageService implements MessageService { @Override public String send() { return "Message from Email service"; } }

注入:

@Autowired private MessageService messageService;

运行结果:

Message from MySQL service

因为MysqlMessageService被标记为@Primary


三、@Qualifier 注解

1. 作用

@Qualifier用于显式指定要注入的 Bean 名称

当存在多个 Bean 时,可以精准指定需要的实现。

2. 示例

@Autowired @Qualifier("emailMessageService") private MessageService messageService;

运行结果:

Message from Email service

四、Spring Bean 注入优先级

Spring 在解析@Autowired时的大致流程:

  1. 按类型查找 Bean

  2. 如果多个 Bean

  3. 优先选择@Primary

  4. 如果仍然冲突

  5. 尝试按字段名匹配

  6. 最终无法确定则抛出异常

优先级总结:

@Qualifier ↓ @Primary ↓ 字段名匹配

因此:

  • @Qualifier优先级最高

  • @Primary负责默认实现


五、最佳实践

推荐在实际项目中:

1️⃣ 使用@Primary指定系统默认实现

2️⃣ 使用@Qualifier指定特殊实现

3️⃣ 避免依赖字段名自动匹配

示例:

@Primary DefaultUserService
@Qualifier("redisUserService")

这样可以让代码更加清晰、可维护性更高


六、总结

@Primary@Qualifier是 Spring 解决多实现类依赖注入问题的核心机制。

注解作用
@Primary指定默认 Bean
@Qualifier指定具体 Bean

理解它们的注入优先级,对于开发大型 SpringBoot 项目非常重要。


如果这篇文章对你有帮助,欢迎收藏或分享。

本文的参考代码链接已经开源,地址:https://github.com/LetMyTearsFlow/SpringBootGuide/tree/main/PrimaryQualifier

如果对你有帮助,欢迎点击Star收藏,后续的SpringBoot代码示例都会在这里更新。

http://www.jsqmd.com/news/493668/

相关文章:

  • 不止调亮度!晚上玩手机的 “护眼全链路” 设置指南
  • 电动汽车高压平台采用率持续上升
  • 基于PP-DocLayoutV3的VMware虚拟机文档自动化管理
  • 机械毕业设计选题指南:从工程问题到技术实现的选题方法论
  • Qwen2-VL-2B-Instruct保姆级部署教程:Windows系统下Docker环境配置详解
  • Ollama部署本地大模型:translategemma-12b-it在国际学校双语教材智能批改中的应用
  • Face Fusion人脸合成实测:3步搞定自然换脸,小白也能成高手
  • HY-MT1.5-1.8B保姆级教程:3步搞定SRT字幕文件智能翻译
  • Retinaface+CurricularFace实战:智能考勤打卡系统快速搭建教程
  • Compose 三层结构设计规范1(基于Slot API)
  • 为什么IP定位总是不准?揭秘IP定位的“精度分层”与选型策略
  • 机械臂构型全解析:从笛卡尔到Delta,哪种最适合你的项目?
  • 低空+公安警务:空天地一体化构建智慧安防新范式,SaaS应用重磅开放
  • 深入人工智能核心:MiniCPM-V-2_6模型架构与训练技术解析
  • OFA模型STM32项目展示:边缘设备图像描述的概念验证
  • ViT: 用transformer架构解决视觉问题
  • Phi-3 Forest Laboratory 开发环境搭建:Ubuntu系统保姆级部署教程
  • 卷积怎么实现?手写 CNN 才让我真正搞懂 im2col
  • 英伟达 NIM API 配置 Claude Code 完整教程(使用 CCR UI)
  • 暗黑破坏神2存档编辑器终极指南:免费开源工具让你的游戏体验更完美
  • 向量数据库存储与检索
  • 01-N8N进阶指南-利用Docker容器化部署与云服务集成实战
  • 微信小程序文件索引化管理与高效检索实践
  • Z-Image-GGUF助力CAD设计:自动生成产品概念草图与渲染图
  • SpringBoot项目在IDEA中无法启动?手把手教你修复启动类识别与依赖问题
  • 揭秘lora-scripts:如何用低资源快速微调,打造你的专属AI助手
  • 语音剪辑神器:Qwen3-ForcedAligner精准定位音频中的每个词语
  • SQL Server容器化实战:用Docker同时运行2017和2008双版本的技巧
  • 腾讯龙虾矩阵落地:企业级AI Agent快速集成最佳实践
  • Windows上安装nvm