[Spring] @Bean 修饰方法时如何注入参数
目录
一、@Bean 的简单使用
1、正常情况
2、问题提出
二、解决方案
1、@Qualifier
2、直接写方法名
三、特殊情况
1、DataSource
一、@Bean 的简单使用
在开发中,基于 XML 文件配置 Bean 对象的做法非常繁琐且不好维护,因此绝大部分情况下都是使用“完全注解开发”。
对于 Spring 而言,IOC 容器中的 Bean 对象的创建和使用是一大重点,Spring 也为我们提供了注解方式创建 bean 对象:使用 @Bean。
在举例之前,先熟悉以下两个需要用到的类:
(1)User 类
package com.demo.pojo;import org.springframework.stereotype.Component;@Component
public class User {private String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +'}';}
}
(2)Book 类
package com.demo.pojo;import org.springframework.stereotype.Component;@Component
public class Book {private User user;public void setUser(User user) {this.user = user;}public User getUser() {return user;}
}
1、正常情况
(1)下面是一个简单的 bean 对象创建:
@Bean
public User getUser() {return new User();
}
经此操作,IOC 中就会多出一个与 <bean id = "getUser" class = "类路径.User"/> 同义的 bean 对象。即:方法名就是 id,返回类型就是 class。
(2)含有普通类型参数的 bean 对象创建:
@Bean
public User getUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;
}
需要注意的是,方法中的参数并不是 bean 对象的成员属性,而是代表着 bean 对象的创建依赖于这几个参数,或许用来 setParameter,或许只是中间变量。
而在 xml 文件中的 <property> 则必须要求用 set 方法。
(3)含有对象类型参数的 bean 对象创建:
package com.demo.config;import com.demo.pojo.Book;
import com.demo.pojo.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;@Configuration
public class Config {@Beanpublic User getUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;}@Beanpublic Book createBook(User user) {Book book = new Book();book.setUser(user);return book;}
}
对比在 xml 中是如何实现参数是对象类型时的属性注入:
(4)正常情况下,@Bean 使用总结
(4-1)@Bean 注解的方法,其返回值就是一个 <bean> 对象,并且注册到了 IOC 容器中。
- id 为方法的名字;
- class 为方法的返回类型;
(4-2)@Bean 对象的实例化依赖于方法内的参数,参数可以是普通类型,也可以是对象类型。
- 若为普通类型,用 @Value("xxx") 来注入这个参数;
- 若为对象类型,则默认情况下,Spring 会到 IOC 容器中寻找与参数类型相同的 bean 对象来注入这个参数;
2、问题提出
根据上述内容,我们会想到:如果参数是对象类型,可是 IOC 中拥有不止一个相同类型的 bean 对象,这该怎么办呢?
比如下面的情况:
可以看到,Book 对象的参数 user 已经报错了,无法自动装配,因为存在多个 User 类型的 Bean,Spring 不知道应该将哪个 bean 注入到 user 中。
二、解决方案
首先我们要知道,默认情况下,参数的注入使用的是 @Autowired,不需要显式写出。
1、@Qualifier
我们可以想到,@Autowired 是根据类型自动装配,当一个类型有多个 bean 对象时失效。
而 @Qualifier 是根据名称进行装配,这不就意味着我们可以用 @Qualifier 来明确需要的 bean 对象嘛。
这有两种写法,都是有效的:
- 直接在参数前加 @Qualifier("function_name");
- 在方法前加 @Qualifier("function_别名"),在参数前加 @Qualifier("function_别名");
(1)配置类
package com.demo.config;import com.demo.pojo.Book;
import com.demo.pojo.User;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;@Configuration
public class Config {@Beanpublic User getUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;}@Beanpublic User createUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;}@Beanpublic Book createBook(@Qualifier("createUser") User user) {Book book = new Book();book.setUser(user);return book;}
}
(2)测试代码
@Test
public void SameObjectTest() {ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);Book book = context.getBean("createBook", Book.class);System.out.println(book.getUser());
}
(3)输出结果
2、直接写方法名
因为一般情况下,方法名不能相同,因此也可以通过将参数名写成对应的方法名来进行注入。
package com.demo.config;import com.demo.pojo.Book;
import com.demo.pojo.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;@Configuration
public class Config {@Beanpublic User getUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;}@Beanpublic User createUser(@Value("wyt") String name) {User user = new User();user.setName(name);return user;}@Beanpublic Book createBook(User createUser) {Book book = new Book();book.setUser(createUser);return book;}
}
三、特殊情况
在这里要说明一些特别的对象类型,比如:DataSource。
1、DataSource
(1)问题描述
@Bean
public DruidDataSource createDruidDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;
}@Bean
public DruidDataSource getDruidDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;
}
当我们像上面的代码一样,写了两个数据源的 bean 对象之后,运行就会出现如下报错:
No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 2
简单来说,就是因为 Spring 有其自身的配置类,导致程序不知道选择哪一个数据源。
(2)解决方法
给其中任意一个加上 @Primary,代表当出现多个同类型 bean 时,优先使用哪一个。写上之后,就可以使用前文所述的方法,如:@Qualifier 或直接写方法名。
@Bean
@Primary
public DruidDataSource createDruidDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;
}
相关文章:

[Spring] @Bean 修饰方法时如何注入参数
目录 一、Bean 的简单使用 1、正常情况 2、问题提出 二、解决方案 1、Qualifier 2、直接写方法名 三、特殊情况 1、DataSource 一、Bean 的简单使用 在开发中,基于 XML 文件配置 Bean 对象的做法非常繁琐且不好维护,因此绝大部分情况下都是使用…...
docker拉取镜像错误 missing signature key
您正在尝试使用 yum 在 CentOS 或 RHEL 系统上安装 docker-ce,但您遇到了一些问题。根据您提供的输出,这里有几个需要注意的点: 系统未注册: "This system is not registered with an entitlement server" 指示您的系统未注册。对于…...

基于可解释性特征矩阵与稀疏采样全局特征组合的人体行为识别
论文还未发表,不细说,欢迎讨论。 Title: A New Solution to Skeleton-Based Human Action Recognition via the combination usage of explainable feature extraction and sparse sampling global features. Abstract: With the development of deep …...

OpenCV4(C++)—— 仿射变换、透射变换和极坐标变换
文章目录 一、仿射变换1. getRotationMatrix2D()2. warpAffine() 二、透射变换三、极坐标变换 一、仿射变换 在OpenCV中没有专门用于图像旋转的函数,而是通过图像的仿射变换实现图像的旋转。实现图像的旋转首先需要确定旋转角度和旋转中心,之后确定旋转…...
http.header.Set()与Add()区别;
在Go语言中进行HTTP请求时,http.Header对象表示HTTP请求或响应的头部信息。http.Header是一个map[string][]string类型的结构,用于存储键值对,其中键表示HTTP头字段的名称,值是一个字符串切片,可以存储多个相同名称的头…...

vue-7-vuex
一、Vuex 概述 目标:明确Vuex是什么,应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具,状态就是数据。 大白话:Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如:购…...

SSO单点登录和OAuth2.0区别
一、概述 SSO是Single Sign On的缩写,OAuth是Open Authority的缩写,这两者都是使用令牌的方式来代替用户密码访问应用。流程上来说他们非常相似,但概念上又十分不同。SSO大家应该比较熟悉,它将登录认证和业务系统分离,…...

【轻松玩转MacOS】基本操作篇
引言 本文是系列的开篇,我将为大家介绍MacOS的基本操作。对于初次接触MacOS的用户来说,掌握这些基本操作是必不可少的。无论是启动和关机,还是使用键盘和鼠标,或者是快捷键的使用,这些基本操作都是你开始使用MacOS的第…...

华为ICT——第三章图像处理基本任务
目录 1:数字图像处理的层次:(处理-分析-理解)顺序不能错: 2:图像处理(图像处理过程): 3:图像分析(特征提取): 4&#x…...
(C++)引用的用法总结
引用(reference)是C极为重要的一部分,本文对其用法进行简单总结。 1. 引用的基本用法 引用的关键字为&,表示取地址的意思,引用变量定义如下: int m 1; int &n m; //定义 cout<<"n:…...

Charles:移动端抓包 / windows客户端 iOS手机 / 手机访问PC本地项目做调试
一、背景描述 1.1、本文需求:移动端进行抓包调试 1.2、理解Charles可以做什么 Charles是一款跨平台的网络代理软件,可以用于捕获和分析网络流量,对HTTP、HTTPS、HTTP/2等协议进行调试和监控。使用Charles可以帮助开发人员进行Web开发、调试…...

【AI】深度学习——人工智能、深度学习与神经网络
文章目录 0.1 如何开发一个AI系统0.2 表示学习(特征处理)0.2.1 传统特征学习特征选择过滤式包裹式 L 1 L_1 L1 正则化 特征抽取监督的特征学习无监督的特征学习 特征工程作用 0.2.2 语义鸿沟0.2.3 表示方式关联 0.2.4 表示学习对比 0.3 深度学习0.3.1 表示学习与深度学习0.3.…...

RK3288:BT656 RN6752调试
这篇文章主要想介绍一下再RK3288平台上面调试BT656 video in的注意事项。以RN6752转接芯片,android10平台为例进行介绍。 目录 1. RK3288 VIDEO INPUT 并口 2. 驱动调试 2.1 RN6752 驱动实现 ①rn6752_g_mbus_config总线相关配置 ②rn6752_querystd配置制式 …...

LLMs 蒸馏, 量化精度, 剪枝 模型优化以用于部署 Model optimizations for deployment
现在,您已经了解了如何调整和对齐大型语言模型以适应您的任务,让我们讨论一下将模型集成到应用程序中需要考虑的事项。 在这个阶段有许多重要的问题需要问。第一组问题与您的LLM在部署中的功能有关。您需要模型生成完成的速度有多快?您有多…...
Milvus踩坑笔记
本文用于记录在学习 Milvus文档时所遇到的一些Bug或报错及解决方法 参考文章: 官方demo:在Dynamic Schema的集合中插入数据 报错1:auto id enabled, id shouldnt in entities[0] 问题描述 此报错出现在Milvus官方在介绍 Dynamic Schema …...

什么是轴电流?轴电流对轴承有什么危害?
根据同步发电机结构及工作原理,由于定子铁芯组合缝、定子硅钢片接缝,定子与转子空气间隙不均匀,轴中心与磁场中心不一致等,机组的主轴不可避免地要在一个不完全对称的磁场中旋转。这样,在轴两端就会产生一个交流电压。…...

react create-react-app v5配置 px2rem (不暴露 eject方式)
环境信息: create-react-app v5 “react”: “^18.2.0” “postcss-plugin-px2rem”: “^0.8.1” 配置步骤: 不暴露 eject 配置自己的webpack: 1.下载react-app-rewired 和 customize-cra-5 npm install react-app-rewired customize-cra…...
.net中用标志位解决socket粘包问题
以下为wpf中, 用标志位"q" 解决粘包问题 using MyFrameWorkWpf.Entities; using System.Collections.ObjectModel; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.…...
【Ubuntu】Systemctl 管理 MinIO 服务器的启动和停止
要使用 systemctl 来管理 MinIO 服务器的启动和停止,您需要创建一个 systemd 服务单元文件,以便 systemd 能够启动和停止 MinIO 服务器。下面是一般的步骤: 创建 systemd 服务单元文件: 打开终端并使用文本编辑器创建一个新的 sys…...
《golang设计模式》第二部分·结构型模式-07-代理模式(Proxy)
文章目录 1. 概述1.1 角色1.2 模式类图 2. 代码示例2.1 设计2.2 代码2.3 示例类图 1. 概述 代理(Proxy)是用于控制客户端访问目标对象的占位对象。 需求:在调用接口实现真是主题之前需要一些提前处理。 解决:写一个代理ÿ…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...