新闻详情

新闻详情

首页 / 资讯中心 / 详情

@Autowired 和 @Qualifier 详解

发布时间:2026/9/30 20:16:03来源:尧图网络
@Autowired 和 @Qualifier 详解
Autowired 和 Qualifier 详解一、Autowired 是什么Autowired是 Spring 提供的依赖注入注解默认按类型byType自动装配。它告诉 Spring 容器这个字段、构造方法或 Setter 方法需要一个依赖请从容器中找一个匹配的 Bean 注入进来。ServicepublicclassUserService{AutowiredprivateUserDaouserDao;}Spring 在创建UserService时扫描到Autowired标记的字段从容器中查找UserDao类型的 Bean通过反射赋值给该字段。二、Autowired 的三种注入位置构造器注入ServicepublicclassUserService{privatefinalUserDaouserDao;publicUserService(UserDaouserDao){this.userDaouserDao;}}如果类只有一个构造方法Autowired可以省略。Spring 4.3 之后默认使用唯一的构造方法进行注入。多个构造方法时必须显式标注ServicepublicclassUserService{privatefinalUserDaouserDao;privatefinalEmailServiceemailService;AutowiredpublicUserService(UserDaouserDao,EmailServiceemailService){this.userDaouserDao;this.emailServiceemailService;}publicUserService(UserDaouserDao){this(userDao,null);}}字段注入ServicepublicclassUserService{AutowiredprivateUserDaouserDao;}代码最简洁但不利于单元测试也无法使用final修饰字段。Setter 注入ServicepublicclassUserService{privateUserDaouserDao;AutowiredpublicvoidsetUserDao(UserDaouserDao){this.userDaouserDao;}}适合依赖可选的场景可以在对象创建后动态替换依赖。三、Autowired 的匹配规则第一步按类型查找Spring 首先在容器中查找与目标类型匹配的 Bean。如果只找到一个直接注入。第二步按名称匹配如果找到多个同类型的 BeanSpring 会用字段名或参数名去匹配 Bean 的名称。ServicepublicclassOrderService{AutowiredprivatePaymentServicealiPayService;// 字段名 aliPayService}如果容器中有aliPayService和wechatPayService两个PaymentService类型的 Bean字段名aliPayService会匹配到对应的 Bean。第三步Primary 优先如果按名称也没有匹配到Spring 会查找标记了Primary的 Bean。ServicePrimarypublicclassAliPayServiceimplementsPaymentService{}第四步Qualifier 指定如果以上都无法确定使用Qualifier显式指定 Bean 名称。AutowiredQualifier(aliPayService)privatePaymentServicepaymentService;匹配流程图按类型查找 ├── 找到一个 → 注入 ├── 找到多个 │ ├── 按字段名/参数名匹配 Bean 名称 │ │ ├── 匹配成功 → 注入 │ │ └── 匹配失败 │ │ ├── 有 Primary → 注入 Primary 标记的 Bean │ │ └── 有 Qualifier → 按 Qualifier 指定的名称注入 │ │ └── 都没有 → 抛 NoUniqueBeanDefinitionException └── 没找到 ├── required true默认→ 抛 NoSuchBeanDefinitionException └── required false → 注入 null四、Autowired 的 required 属性Autowired(requiredfalse)privateUserDaouserDao;默认required true找不到匹配的 Bean 时启动报错。设置为false时找不到则注入null不报错。required false适合可选依赖的场景但要注意使用前判空。五、Qualifier 的作用Qualifier配合Autowired使用在同类型多 Bean 时按名称指定具体注入哪一个。ServicepublicclassOrderService{AutowiredQualifier(aliPayService)privatePaymentServicepaymentService;}Qualifier的值就是目标 Bean 的名称。Bean 名称默认是类名首字母小写也可以显式指定Service(aliPayService)publicclassAliPayServiceimplementsPaymentService{}六、Qualifier 的使用位置字段上AutowiredQualifier(aliPayService)privatePaymentServicepaymentService;构造器参数上ServicepublicclassOrderService{privatefinalPaymentServicepaymentService;publicOrderService(Qualifier(aliPayService)PaymentServicepaymentService){this.paymentServicepaymentService;}}Setter 方法参数上AutowiredpublicvoidsetPaymentService(Qualifier(aliPayService)PaymentServicepaymentService){this.paymentServicepaymentService;}方法参数上Bean 方法BeanpublicOrderServiceorderService(Qualifier(aliPayService)PaymentServicepaymentService){returnnewOrderService(paymentService);}七、Qualifier 与 Primary 的优先级当两者同时存在时Qualifier的优先级更高。ServicePrimarypublicclassAliPayServiceimplementsPaymentService{}ServicepublicclassWechatPayServiceimplementsPaymentService{}ServicepublicclassOrderService{AutowiredQualifier(wechatPayService)// 显式指定覆盖 PrimaryprivatePaymentServicepaymentService;// 注入 WechatPayService}Qualifier是精确指定Primary是默认首选。精确指定优先于默认。八、Qualifier 用于集合注入当注入集合类型时Qualifier可以筛选特定名称的 BeanAutowiredQualifier(aliPayService)privateListPaymentServicepaymentServices;但这只对按名称匹配的 Bean 有效。更常见的做法是给 Bean 加上自定义注解然后用Qualifier筛选。九、自定义 Qualifier 注解Spring 支持通过自定义注解扩展Qualifier的能力Target({ElementType.FIELD,ElementType.PARAMETER})Retention(RetentionPolicy.RUNTIME)QualifierpublicinterfaceAliPay{}使用ServiceAliPaypublicclassAliPayServiceimplementsPaymentService{}ServicepublicclassOrderService{AutowiredAliPayprivatePaymentServicepaymentService;}这种方式比字符串名称更类型安全重构时 IDE 能自动更新。十、底层原理处理类Autowired和Qualifier由AutowiredAnnotationBeanPostProcessor处理。它实现了BeanPostProcessor接口在 Bean 实例化后、初始化前介入。处理时机实例化 → 属性填充populateBean └── AutowiredAnnotationBeanPostProcessor.postProcessProperties() ├── 扫描字段和方法上的 Autowired ├── 解析依赖类型 ├── DefaultListableBeanFactory.resolveDependency() │ ├── 按类型查找 │ ├── 按 Qualifier 筛选 │ ├── 按 Primary 选择 │ └── 按名称匹配 └── 反射注入核心方法// AutowiredAnnotationBeanPostProcessorpublicPropertyValuespostProcessProperties(PropertyValuespvs,Objectbean,StringbeanName){// 1. 查找注入元数据InjectionMetadatametadatafindAutowiringMetadata(beanName,bean.getClass(),pvs);// 2. 执行注入metadata.inject(bean,beanName,pvs);returnpvs;}// DefaultListableBeanFactorypublicObjectresolveDependency(DependencyDescriptordescriptor,StringrequestingBeanName,SetStringautowiredBeanNames,TypeConvertertypeConverter){// 1. 如果字段类型是 Optional、ObjectProvider 等特殊处理// 2. 查找匹配的 BeanObjectresultdoResolveDependency(descriptor,requestingBeanName,autowiredBeanNames,typeConverter);returnresult;}doResolveDependency()中会检查Qualifier注解的值如果有就按名称匹配如果没有走类型匹配逻辑。十一、Autowired vs Resource对比维度AutowiredResource来源SpringJSR-250JDK默认匹配按类型按名称指定名称Qualifiername属性required 属性支持不支持构造器注入支持不支持处理类AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor// Autowired QualifierAutowiredQualifier(userDaoImpl)privateUserDaouserDao;// ResourceResource(nameuserDaoImpl)privateUserDaouserDao;两者功能等价Resource写起来更简洁但Autowired功能更丰富支持构造器注入、required false。十二、常见问题1. NoUniqueBeanDefinitionExceptionNoUniqueBeanDefinitionException: expected single matching bean but found 2容器中有多个同类型 Bean且无法按名称匹配。解决方案用Qualifier指定名称用Primary标记首选将字段名改为与目标 Bean 名称一致2. NoSuchBeanDefinitionExceptionNoSuchBeanDefinitionException: No qualifying bean of type UserDao available容器中没有匹配的 Bean。检查目标类是否被 Spring 管理包路径是否在ComponentScan范围内是否设置了required false3. 构造器注入循环依赖构造器注入无法解决循环依赖启动报BeanCurrentlyInCreationException。应通过重构消除循环依赖或改用字段注入。4. Qualifier 值写错Qualifier的值必须与 Bean 名称完全一致大小写敏感。Bean 默认名称是类名首字母小写显式指定时以指定值为准。5. 自定义 Qualifier 注解不生效检查自定义注解是否标注了Qualifier元注解且Retention为RUNTIME。十三、最佳实践优先使用构造器注入。保证依赖不可变、完全就绪便于单元测试。同类型多 Bean 时优先用自定义 Qualifier 注解。比字符串名称更类型安全重构友好。Qualifier 的粒度要细。一个Qualifier只对应一个 Bean不要一个名称对应多个。避免字段注入。不利于测试容易积累过多依赖而不自知。Primary 用于设置合理的默认值。当大多数场景都用某个实现时标记它为Primary特殊情况再用Qualifier指定。Qualifier 与 Primary 配合使用。Primary提供默认Qualifier处理例外。十四、总结维度AutowiredQualifier作用标记需要注入的依赖指定注入的具体 Bean匹配方式先按类型再按名称按名称单独使用可以通常配合 Autowired优先级低于 Qualifier高于 Primary支持位置字段、构造器、Setter、参数字段、构造器参数、Setter 参数、方法参数处理类AutowiredAnnotationBeanPostProcessor同上Autowired负责“需要一个依赖”Qualifier负责“要哪一个”。当容器中只有一个匹配类型的 Bean 时Autowired就能完成注入当有多个时Qualifier用来消除歧义。两者配合使用是 Spring 依赖注入中最常见的组合。理解它们的匹配规则和优先级能帮你快速定位注入异常写出更清晰的依赖关系。f
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

真空封装设备在医疗电子中的应用解析 2026/9/30 20:53:12

真空封装设备在医疗电子中的应用解析

医疗电子器件的封装为什么格外强调真空环境?核心在于水汽与气泡会直接削弱器件的长期可靠性。真空封装设备在医疗电子中的应用,本质是把腔体气压、升温曲线与气氛控制整合进同一工艺窗口,让植入式传感器、微流控芯片这类对洁净度敏感的器件获…

阅读更多 →
金种子酒换届接力锚定战略航向 健康业绩观蓄力高质量发展 2026/9/30 20:53:12

金种子酒换届接力锚定战略航向 健康业绩观蓄力高质量发展

9月28日,金种子酒(600199.SH)召开2026年第一次临时股东会,完成董事会换届选举,选举产生第八届董事会6名非独立董事、3名独立董事。同日,第八届董事会第一次会议选举靳健先生为董事长,聘任谢金明…

阅读更多 →
SpringBoot+SSM书画拍卖网站实战:从表设计到并发出价与部署 2026/9/30 20:52:46

SpringBoot+SSM书画拍卖网站实战:从表设计到并发出价与部署

做“springboot_ssm865书画拍卖网站”这类项目的,我接触过不少。有毕设学生,有想接私活的开发者,也有真正手里囤了一批书画资源、打算做个线上拍卖渠道的商家。这个标题看起来只是技术栈的堆叠,但拆开看,它其实是一个很…

阅读更多 →
双样本T检验的四大前提与实战避坑指南 2026/9/30 20:52:46

双样本T检验的四大前提与实战避坑指南

1. 为什么双样本T检验不是“套公式就能出结果”的数学题 双样本T检验&#xff0c;这个词在统计学入门课里常被简化成“比较两组平均数是否不同”&#xff0c;但实际工作中&#xff0c;我见过太多人把原始数据往Excel的T.TEST函数里一塞&#xff0c;看到p<0.05就拍板“有显著…

阅读更多 →
Node.js连接Redis实战:环境配置、ioredis接入与避坑指南 2026/9/30 20:52:46

Node.js连接Redis实战:环境配置、ioredis接入与避坑指南

1. 准备阶段&#xff1a;Node.js和Redis环境怎么搭才不踩坑先说一个常见的尴尬场景&#xff1a;你以为“Node.js连接Redis”的核心工作就是npm install redis然后写几行代码&#xff0c;结果卡在第一步——node -v不好使、npm 报一堆权限错、Redis 服务根本没起来。我见过太多小…

阅读更多 →
SSM+OpenCV轻量人脸门禁系统实战指南 2026/9/30 20:52:46

SSM+OpenCV轻量人脸门禁系统实战指南

简介&#xff1a;本资源是一份面向高校计算机类专业本科生与毕业设计指导教师的完整毕业设计文档&#xff0c;聚焦基于人脸识别技术的学生宿舍智能化管理方案&#xff0c;解决传统人工登记效率低、安全性弱等实际管理痛点。文档采用SSM&#xff08;SpringSpring MVCMyBatis&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉