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

Spring注解@Qualifier的详细用法你知道几种「扩展点实战系列」- 第444篇

历史文章(文章累计440+)

《国内最全的Spring Boot系列之一》

《国内最全的Spring Boot系列之二》

《国内最全的Spring Boot系列之三》

《国内最全的Spring Boot系列之四》

《国内最全的Spring Boot系列之五》

SpringBoot/Spring扩展点系列之初始化和销毁的3种办法 - 第438篇

观察者模式实际应用场景「扩展点实战系列」- 第439篇

服务信息上报+记录请求信息+监听项目运行状态还能这么玩「扩展点系列」- 第440篇

配置类信息赋值为Java静态变量「扩展点实战系列》」- 第441篇

3种方案扩展RestTemplate让其具备负载均衡(超级详细)「扩展点实战系列」- 第442篇

一个注解@LoadBalanced就能让RestTemplate拥有负载均衡的能力?「扩展点实战系列」- 第443篇

​悟纤:师傅,这一节,看着比较简单呢?

师傅:嗯嗯,这一节就是和大家分享一些一些基础的知识,基础功不打扎实一点的话,源码和高级一些的功能在实现的时候就没有思路了。

师傅:扎实基本功,敲码更轻松。

悟纤:师傅说的是,我一定会打好基础的。

师傅:孺子可教也。

悟纤:那咱们赶紧开始吧~ 我已经按耐不住想体验学习的快乐了!

导读

在前面小节中,在实现Ribbon的负载均衡提到一个很重要的注解@Qualifier,可能还有很多的小伙伴对于这个注解,还有点懵逼的状态,这一节的话就讲讲@Qualifier为什么需要存在,以及常见的几种方法。

 👇👇👇扩展点实战系列

01.观察者模式实际应用场景「扩展点实战系列」

02.服务信息上报+记录请求信息+监听项目运行状态还能这么玩🐴「扩展点实战系列」

03.配置类信息赋值为Java静态变量「扩展点实战系列》」

04. 3种方案扩展RestTemplate让其具备负载均衡(超级详细)「扩展点实战系列」

05.一个注解@LoadBalanced就能让RestTemplate拥有负载均衡的能力?「扩展点实战系列」》

06.Spring注解@Qualifier的详细用法你知道几种「扩展点实战系列」

07.「待拟定」《利用Spring扩展点模拟FeignClient实现远程调用(干货满满)「扩展点实战系列」》

一、为什么需要@Qualifier

有句话说:知其然之所以然,知道它是这样的,更知道它为什么是这样的。

在使用之前呢,先要了解一下存在的价值和意义。

1.1 装配Bean的两种方式

这个还需要从转配Bean说起。

@Autowired与@Resource都可以用来装配Bean。

区别:

(1)@Autowired:Spring注解,默认按类型装配,默认情况下必须要求依赖对象必须存在。如果 Spring 没有其他提示,将会按照需要注入的变量名称来寻找合适的 bean。

(2)@Resoure:JavaEE注解,默认按照名称进行装配,可以通过name属性指定名称,如果没有指定name属性,当注解写在字段上时,默认取字段名进行查找注入,如果写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

从这个区别可以看出@Resouce还是非常强大的,各种情况都满足了。

那么对于@Autowired呢?作为Spring框架提供的注解,肯定也不至于不考虑常规的一些情况吧。

1.2 @Autowired

对于@Resouce基本满足了大部分装配的场景,而对于@Autowired的话,它自己就不能单干了,看如下这种场景:

这里声明了两个相同类型的bean,那么如果使用@Autowired进行装配的话:

此时就会报错:

required a single bean, but 2 were found

在上面@Autowired也是按照名称去寻找的,如果这里的名称修改为curDate的话:

此时装配进去一个是curDate(),可以看到打印的信息:

[Mon Sep 05 12:14:33 CST 2022]

1.3 @Qulifier

如果我们希望转配的是nextYear()的话,就需要使用@Qulifier(当然你把变量名称修改为nextYear也是一种方式),看下这个单词的意思:

合格者,也就是哪个Spring Bean是合格的,满足要求的。

再看另外一个解释:

限定符,这个可能在Spring描述的会更贴切,限定了只能是指定的名称的Spring Bean。

所以我们只需要在添加注解@Qualifier进行名称:

结果:

[Tue Sep 05 12:14:33 CST 2023]

当然这只是@Qualifier存在的一种情况,那么它还具备什么神奇的功效呢?

二、@Qualifier的各种用法

接下来就带着大家看看@Qualifier的各种奇淫技巧。

2.1 常规用法限定注入类

通过前面的示例已经了解了可以使用@Qualifier限定类的注入:

说明:用来限定注入的Bean的名称。

2.2 @Qualifier筛选注入对象

当有多个实例的时候,Spring的@Autowired支持注入到一个集合中:

打印结果:

[Mon Sep 05 12:14:33 CST 2022, Tue Sep 05 12:14:33 CST 2023]

接下来使用@Qulifier进行限定一下:

在使用的时候:

结果就只有一个数据了:

[Tue Sep 05 12:13:49 CST 2023]

说明:@Qualifier起到了一个筛选的作用只有Bean上加有@Qualifier注解的Bean才会被收集注入。

2.3自定义注解筛选注入对象

就如同ribbon的@LoadBalanced可以自定义注解类来限定注入Bean:

/** * 自定义注解 * * @author 悟纤「公众号SpringBoot」 * @date 2022-09-05 * @slogan 大道至简 悟在天成 */@Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Qualifierpublic @interface QualifierDate {}

在自定义注解上的注解称为元注解,具体都代表什么意思?如果你还不是很懂的话,可以关注公众号「SpringBoot」回复关键词[404],查看文章

《Spring Boot @ConditionalOnClass上的注解你了解多少-java元注解和注解 - 第404篇》

在注入Bean的时候就以使用QualifierDate注解:

/** 当前日期,应该是2022年*/@Beanpublic Date curDate(){    return new Date();}/**明年日期 ,应该是2023年*/@Bean@QualifierDatepublic Date nextYear(){    Calendar ca = Calendar.getInstance();//得到一个Calendar的实例    ca.setTime(new Date());  //设置时间为当前时间    ca.add(Calendar.YEAR, +1); //年份+1    return ca.getTime();}

那么在注入到集合的时候,就可以使用@QualifierDate来限定:

@Autowired@QualifierDateList<Date> dates = Collections.emptyList();

执行的结果和2.2的结果是一样。

总结

最后对于本文简单做个总结:

(1)@Qualifier是一个限定符号,用来限定注入类以及筛选注入对象。

(2)当一个项目中存在多个同类型的Bea你的时候,避免报required a single bean, but 2 were found的方案有如下几种:

①方案1:通过名称来自动注入,定义的变量名称和注入的bean的名称是一样的。

②方案2:使用@Qualifier限定符号,在类上添加@Qualifier注解限定注入类。

③方案3:使用@Primary定义首选项,只需要在注入Bean上添加@Primary定义首选项,那么该Bean就会作为首选进行注入。

相关文章:

  • uni-app 微信小程序中关于 map 地图使用案例分享
  • 工业级成熟航运港口人工智能产品全球前三船公司及港口码头落地,中国上海人工智能独角兽中集飞瞳全球应用最广规模最大最先进港航AI企业
  • CSS基础篇---02选择器进阶、背景样式、显示模式
  • 【C语言】自定义类型 —— 结构体
  • 千万级用户ms级抽奖N名设计方案
  • 2022第五空间WEBMISC
  • 说几句得罪人的大实话
  • Spark 优化 (二) --------- Spark 数据倾斜
  • 第01篇:系统化学习, 搞定Spring容器管理
  • 【Android】-- Intent(显式和隐式Intent)
  • 【HashMap】HashMap的6种遍历方法
  • 网络中其他重要技术与协议(DNS系统,ICMP协议,NAT技术与代理服务器)
  • [仅需1步]企业微信群机器人[0基础接入][java]
  • 关于 vue keep-live 缓存时候,缓存页面高度不生效问题 :
  • 对比勒索病毒和熊猫烧香,谈如何保证服务器端数据安全?
  • emacs初体验
  • httpie使用详解
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 构建工具 - 收藏集 - 掘金
  • 后端_ThinkPHP5
  • 如何胜任知名企业的商业数据分析师?
  • 十年未变!安全,谁之责?(下)
  • 使用 QuickBI 搭建酷炫可视化分析
  • 学习使用ExpressJS 4.0中的新Router
  • nb
  • 1.Ext JS 建立web开发工程
  • NLPIR智能语义技术让大数据挖掘更简单
  • !!java web学习笔记(一到五)
  • #if #elif #endif
  • #pragma 指令
  • #QT(串口助手-界面)
  • #控制台大学课堂点名问题_课堂随机点名
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (七)Java对象在Hibernate持久化层的状态
  • (三)终结任务
  • (算法)求1到1亿间的质数或素数
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .form文件_一篇文章学会文件上传
  • .NET Core中Emit的使用
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .net6Api后台+uniapp导出Excel
  • .net程序集学习心得
  • .NET程序员迈向卓越的必由之路
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • [<事务专题>]
  • [AIGC] Java 和 Kotlin 的区别
  • [BZOJ1010] [HNOI2008] 玩具装箱toy (斜率优化)
  • [C/C++随笔] char与unsigned char区别
  • [C++]18:set和map的使用
  • [EFI]Dell Latitude-7400电脑 Hackintosh 黑苹果efi引导文件
  • [hdu 4552] 怪盗基德的挑战书