关于Qualifier你要知道的二三事

news2024/11/18 22:43:58

image.png

🍞 @Qualifier注解的作用-定义Bean-指定Bean的名称

@Qualifier注解可以区分具有相同类型的多个Bean,用于明确指定要注入的Bean的名称或限定符。通过为要注入的Bean添加 @Qualifier注解,你可以告诉Spring应该使用哪个Bean,以解决Spring框架中依赖注入时的歧义性问题。

假设我们有一个名为"UserService"的服务接口,有多个实现类可以用于不同的业务逻辑。现在,我们需要在另一个类中注入"UserService",但由于有多个实现类可用,我们需要明确指定要注入的具体实现类。

示例代码如下:

public interface UserService {
    void performAction();
}

@Component
@Qualifier("implementationA")
public class UserServiceImplA implements UserService {
    public void performAction() {
        System.out.println("Performing action with UserServiceImplA");
    }
}

@Component
@Qualifier("implementationB")
public class UserServiceImplB implements UserService {
    public void performAction() {
        System.out.println("Performing action with UserServiceImplB");
    }
}

@Component
public class UserClient {
    @Autowired
    @Qualifier("implementationA")
    private UserService userService;

    public void doSomething() {
        userService.performAction();
    }
}

错误的案例:

@Component
public class UserClient {
    @Autowired
    private UserService userService;

    public void doSomething() {
        userService.performAction();
    }
}

明确:@Autowired注解是按照类型注入Bean。由于UserServiceImplA、UserServiceImplB都是实现自接口UserService,因此在Spring注入过程中,会导致Spring不知道该注入哪个Bean的实现。 注入时,如果不使用该注解,会报以下的异常:

NoUniqueBeanDefinitionException异常是Spring框架中的一个异常,它表示在自动装配(Autowired)过程中无法确定要注入的bean,因为有多个符合条件的bean可用。

在上面的示例中,我们定义了一个"UserService"接口,并有两个实现类"UserServiceImplA"和"UserServiceImplB"。在"UserClient"类中,我们使用@Autowired注解注入"UserService"接口,并使用@Qualifier注解标记要注入的具体实现类。

通过@Qualifier(“implementationA”),我们明确指定了要注入的是"UserServiceImplA"实现类。这样,当"UserClient"类中使用"userService"时,将调用"UserServiceImplA"的实现方法。

通过@Qualifier注解,我们能够精确选择要注入的特定Bean,解决了存在多个相同类型的Bean时的歧义问题。

🥐 同类型的Bean注入知识拓展

如果存在多个Bean,它们具有相同的类型但不同的名称,那么在注入这些Bean时不会抛出NoUniqueBeanDefinitionException异常。相反,Spring会根据类型进行自动装配,选择与目标类型匹配的Bean进行注入。

以下是一个示例,演示具有相同类型但不同名称的多个Bean的自动装配:

@Component("userService")
public class UserService {
    public void performAction() {
        System.out.println("Performing action in UserService");
    }
}

@Component("adminService")
public class AdminService {
    public void performAction() {
        System.out.println("Performing action in AdminService");
    }
}

现在,我们可以在另一个类中使用@Autowired注解来注入这两个Bean:

@Component
public class ServiceClient {
    @Autowired
    private UserService userService;

    @Autowired
    private AdminService adminService;

    public void performServiceAction() {
        userService.performAction();
        adminService.performAction();
    }
}

在上述示例中,ServiceClient类成功地注入了UserService和AdminService两个不同名称但相同类型的Bean,因为它们都是被@Component注解标记的Spring管理的Bean。

总结起来,当存在具有相同类型但不同名称的多个Bean时,Spring可以根据类型进行自动装配,选择合适的Bean进行注入,而不会抛出异常。只有当存在多个相同类型的Bean且没有提供明确的标识符时,才会抛出NoUniqueBeanDefinitionException异常。

🥖 @Qualifier注解的作用-注入Bean-配合@Configuration使用

当在一个业务Bean中存在多个同类型的Bean时,可以使用@Qualifier注解来指定要注入的具体Bean。

@Configuration
public class AppConfig {

    @Bean
    @Qualifier("database")
    public DataSource dataSource() {
        // 返回一个数据库数据源的实现
        return new DatabaseDataSource();
    }

    @Bean
    @Qualifier("file")
    public DataSource fileDataSource() {
        // 返回一个文件数据源的实现
        return new FileDataSource();
    }

    @Bean
    public DataProcessor dataProcessor(@Qualifier("database") DataSource dataSource) {
        // 通过@Qualifier注解指定要注入的数据源为"database"
        return new DataProcessor(dataSource);
    }
}
public interface DataSource {
    void connect();
    void disconnect();
}

public class DatabaseDataSource implements DataSource {
    @Override
    public void connect() {
        System.out.println("Connecting to the database...");
        // 连接数据库的具体实现逻辑
    }

    @Override
    public void disconnect() {
        System.out.println("Disconnecting from the database...");
        // 断开数据库连接的具体实现逻辑
    }
}

public class FileDataSource implements DataSource {
    @Override
    public void connect() {
        System.out.println("Connecting to the file system...");
        // 连接文件系统的具体实现逻辑
    }

    @Override
    public void disconnect() {
        System.out.println("Disconnecting from the file system...");
        // 断开文件系统连接的具体实现逻辑
    }
}

在上面的例子中,通过@Configuration注解标记了一个配置类AppConfig。在该配置类中定义了两个名为dataSource和fileDataSource的Bean方法,并分别使用@Qualifier注解指定了它们的限定符为"database"和"file"。

接着,在dataProcessor方法上,使用@Qualifier(“database”)注解来指定要注入的数据源为名为"database"的Bean。这样,在其他地方使用@Autowired或@Inject注解注入DataProcessor时,就会根据@Qualifier注解指定的限定符来选择正确的Bean进行注入。

🥓 总结

由此可见,关于 @Qualifier注解,在Spring中的主要作用有两个:

  • 在定义Bean的地方,使用@Qualifier注解为Bean添加一个限定符,这个限定符可以是任何字符串,用于区分同一类型的多个Bean。
@Bean
@Qualifier("database")
public DataSource dataSource() {
    // 返回一个数据库数据源的实现
    return new DatabaseDataSource();
}
  • 在需要进行注入Bean的地方,使用@Qualifier注解并指定相同的限定符值,具体来说,假设有两个名为"databaseDataSource"和"fileDataSource"的DataSource类型的Bean,并且它们都使用了@Qualifier注解并指定了不同的限定符值。
@Autowired
@Qualifier("database")
private DataSource dataSource;

🫓 从源码中看@Qualifier注解

内容待完善中…

写在最后

感谢您读到这里,如果觉得文章写的还不错或有任何疑问,可以添加我微信,我随时为您解答。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1081980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

黑马JVM总结(三十一)

(1)类加载器-概述 启动类加载器-扩展类类加载器-应用程序类加载器 双亲委派模式: 类加载器,加载类的顺序是先依次请问父级有没有加载,没有加载自己才加载,扩展类加载器在getParent的时候为null 以为Boots…

zabbix监控实战1

1、zabbix监控平台部署 重新克隆纯净虚拟机 数据库初始化 修改密码为WHqwerty123 初始化完成 创建zabbix数据库 基础配置和服务启动 访问 2、zabbix添加监控节点 修改字体文件 在客户端 手动添加监控节点 自动添加监控节点 3、zabbix api 自动注册 停掉自动发现 删掉serve…

VMware 下模拟软 RAID 的创建及故障恢复

Author:rab 目录 前言一、创建 RAID1.1 环境1.2 什么是 RAID?1.3 软 RAID 和硬 RAID1.4 如何创建软 RAID? 二、故障模拟与数据恢复2.1 故障模拟2.2 故障恢复 思考? 前言 一块物理硬盘要投入生产使用,一般会经历一下这…

面试经典 150 题 2 —(滑动窗口)— 3. 无重复字符的最长子串

3. 无重复字符的最长子串 方法 class Solution { public:int lengthOfLongestSubstring(string s) {int result 0, length s.length();int start 0, end 0;while(end < length){// 发现有重复字符时&#xff0c;可以直接把左指针移动到第一个重复字符的下一个位置for(i…

Web前端-Vue2+Vue3基础入门到实战项目-Day3(生命周期, 案例-小黑记账清单, 工程化开发入门)

Web前端-Vue2Vue3基础入门到实战项目-Day3 生命周期生命周期 & 生命周期四个阶段生命周期钩子生命周期案例created应用mounted应用 案例 - 小黑记账清单工程化开发入门工程化开发和脚手架项目运行流程index.htmlmain.js 组件化组件注册局部注册全局注册 来源 生命周期 生命…

1312. 序列统计

1312. 序列统计 - AcWing题库 L~R范围可以等同于0~R-L范围 相当于在R-L1个数中选出k个数 令 则变为 相当于在R-Lk个数中选出k个数 需要计算 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;t…

Filter(过滤器)Intercerptor(拦截器)

Filter过滤器 顾名思义&#xff0c;Filter可以对请求进行过滤&#xff0c;当浏览器发送请求时&#xff0c;首先先会被Filter进行拦截&#xff0c;Filter可以决定此次拦截是否放行&#xff0c;如果选择放行&#xff0c;放行之后还会返回Filter执行剩下的代码。 使用方法&…

YOLOv7独家改进:Multi-Dconv Head Transposed Attention注意力,效果优于MHSA| CVPR2022

💡💡💡本文独家改进:Multi-Dconv Head Transposed Attention注意力,可以高效的进行高分辨率图像处理,从而提升检测精度 MDTA | 亲测在多个数据集能够实现大幅涨点 收录: YOLOv7高阶自研专栏介绍: http://t.csdnimg.cn/tYI0c ✨✨✨前沿最新计算机顶会复现 �…

初识Java 13-2 异常

目录 标准Java异常 新特性&#xff1a;更好的NullPointerException报告机制 使用finally执行清理 finally有什么用 在return时使用finally 缺陷&#xff1a;异常丢失 异常的约束 构造器 本笔记参考自&#xff1a; 《On Java 中文版》 标准Java异常 Throwable类描述了任…

项目生命周期

阶段 项目经理或组织可以将每一个项目划分为若干个阶段&#xff0c;以便于有效地进行管理控制&#xff0c;并实施该项目组织的日常运作联系起来。 项目划分为四个阶段&#xff1a;概念、计划、实施、结束 生命期 项目阶段合在一起称为项目生命期&#xff0c;项目生命期确定了将…

Go流程控制与快乐路径原则

Go流程控制与快乐路径原则 文章目录 Go流程控制与快乐路径原则一、流程控制基本介绍二、if 语句2.1 if 语句介绍2.2 单分支结构的 if 语句形式2.3 Go 的 if 语句的特点2.3.1 分支代码块左大括号与if同行2.3.2 条件表达式不需要括号 三、操作符3.1 逻辑操作符3.2 操作符的优先级…

【k8s】ingress-nginx通过header路由到不同后端

K8S中ingress-nginx通过header路由到不同后端 背景 公司使用ingress-nginx作为网关的项目&#xff0c;需要在相同域名、uri&#xff0c;根据header将请求转发到不同的后端中在稳定发布的情况下&#xff0c;ingress-nginx是没有语法直接支持根据header做转发的。但是这个可以利…

ubuntu配置yolov5环境

本文硬件平台为工控机&#xff0c;系统环境为ubuntu18 配置yolov5步骤 1.下载pytorch和torchvision软件包 由于在线安装容易出现安装失败&#xff0c;所以本文使用的是本地安装。本文是基于miniconda安装的&#xff0c;miniconda安装参考之前的博客&#xff1a;ubuntu中安装m…

ssm+vue的台球厅管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的台球厅管理系统(有报告)。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring S…

差模电感和共模电感的差别

一、初步了解差模、共模的概念 超链接&#xff0c;点击鼠标打开&#xff1a;X电容和Y电容&#xff1b;差模与共模初认识 二、差模和共模电感的二者区别 共模电感和差模电感&#xff0c;是电路中常用的滤波电感、EMI器件&#xff0c;两者经常以环形电感线圈的方式存在。 首先…

理解http中cookie!C/C++实现网络的HTTP cookie

HTTP嗅探&#xff08;HTTP Sniffing&#xff09;是一种网络监控技术&#xff0c;通过截获并分析网络上传输的HTTP数据包来获取敏感信息或进行攻击。其中&#xff0c;嗅探器&#xff08;Sniffer&#xff09;是一种用于嗅探HTTP流量的工具。 在HTTP嗅探中&#xff0c;cookie是一…

Python一步到位实现图像转PDF自动化处理详解

什么是 img2pdf 库&#xff1f; img2pdf 是一个 Python 库&#xff0c;它可以让你轻松地把多张图像转换为 PDF 文件。它支持多种图像格式&#xff0c;如 JPG, PNG, GIF, BMP 等&#xff0c;并且可以自动调整图像的大小和方向&#xff0c;以适应 PDF 的页面大小和方向。它还可以…

跨域问题-笔记

这里写目录标题 一、什么是跨域&#xff1a;二、跨域问题解决思路&#xff1a;1.从浏览器入手2.从域名入手3.从jsonp入手4.从代理入手 一、什么是跨域&#xff1a; 跨域指的是不同服务器之间不能相互访问各自的资源或者数据&#xff0c;这出于一个策略——“同源策略”&#x…

【力扣】2578. 最小和分割

【力扣】2578. 最小和分割 文章目录 【力扣】2578. 最小和分割1. 题目介绍2. 思路3. 解题代码4. 疑问&#xff1f;5. Danger参考 1. 题目介绍 给你一个正整数 num &#xff0c;请你将它分割成两个非负整数 num1 和 num2 &#xff0c;满足&#xff1a; num1 和 num2 直接连起来…

Python 入门

目录 1 Python介绍1.1 特点1.2 什么时候不应该用Python1.3 Python解释器 2 IDLE开发环境使用入门2.1 IDLE 两种模式2.2 IDLE常用快捷键 3 程序基本格式4 图形化程序设计5 绘制奥运五环 声明&#xff1a;本文作为自己的学习笔记&#xff0c;欢迎大家于本人学习交流&#xff0c;转…