[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;
}

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

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

相关文章

持续集成部署-k8s-资源调度:标签和选择器

持续集成部署-k8s-资源调度:标签和选择器 1. 标签选择器介绍2. 标签的应用2.1 创建 Pod 并添加标签2.2 对现有资源新增标签2.3 修改 Label 值3. 选择器的应用1. 标签选择器介绍 在 Kubernetes 中,标签(Labels)和选择器(Selectors)是用于对资源进行分类和识别的关键概念。…

【新的小主机】向日葵远程控制ubuntu

向日葵远程控制ubuntu 一、简介二、问题及解决方法2.1 向日葵远程连接Ubuntu22主机黑屏&#xff1f;2.2 Ubuntu如何向日葵开机自启&#xff1f;2.3 无显示器情况下&#xff0c;windows远程桌面连接Ubuntu? 三、美化桌面3.1 安装/解压3.2 设置3.3 右上角显示实时网速 四、安装d…

运营人必备这个微信运营工具

微信管理系统CRM在各行各业都有应用的场景---IT互联网、制造业、商业服务、金融投资、教育培训、房产家装、电商、政务等20行业领域均得到广泛应用。 微信CRM管理系统的主要功能&#xff1a; 多个微信号聚合聊天&#xff1a;解决多个微信来回切换&#xff0c;换着手着手机的麻烦…

Chrome出现STATUS_STACK_BUFFER_OVERRUN解决方法之一

Chrome出现STATUS_STACK_BUFFER_OVERRUN错误代码&#xff0c;setting都无法打开 解决方法1&#xff1a;兼容性设置为win7 解决方法2&#xff1a; 1&#xff0c;开始菜单搜索Exploit Protection 2&#xff0c;添加程序进行自定义&#xff0c;点号&#xff0c;按程序名称添加 …

Spring MVC程序开发(JavaEE进阶系列3)

目录 前言&#xff1a; 1.什么是Spring MVC 1.1MVC的定义 1.2MVC和Spring MVC的关系 1.3为什么要学习Spring MVC 2.Spring MVC项目的创建 3.Spring MVC框架的使用 3.1连接的功能 3.1.1RequestMapping 3.1.2GetMapping 3.1.3PostMapping 3.2获取参数的功能 3.2.1获…

高通camx开源部分学习简介

camera整体框架 sensor 上电&#xff0c;通过 MIPI协议传输&#xff0c;得到RAW图像数据。RAW图像数据经过ISP处理&#xff0c;得到YUV图像数据。YUV图像数据再经过DMA传输到DDR内存中&#xff0c;DDR内存也就是上图中标识的HOST。每个厂家的 ISP原理和功能大致相同&#xff0c…

内外网结合的多服务发布架构

1. 需求 1&#xff09;有多个独立的web服务需要对外发布。 2&#xff09;有AIGC的大模型服务需要在内网图形工作站上运行&#xff0c;也需要对外发布接口。 3&#xff09;所有服务需要通过域名访问。 2. 现有资源 1&#xff09;阿里云上的ECS云服务器一台&#xff0c;考虑…

文件系统数据

流 在.NET Framework中进行的所有输入和输出工作都要用到流(stream)。流是序列化设备的抽象表示。序列化设备可以线性方式存储数据&#xff0c;并按照同样的方式访问&#xff1a;一次访问一个字节。 此设备可以是磁盘文件、网络通道、内存位置或其他支持一线性方式读写的对象…

【亲测有效】C盘容量满了,给C盘扩容!!!

前言 相信有很多小伙伴用自己电脑的时候明明不往C盘装东西&#xff0c;但是C盘还是慢慢的变红了&#xff0c;我也是因为C盘满了而备受困扰。又不知道如何解决或者怕自己鼓捣着磁盘数据没了。闲来无事&#xff0c;我查了一些资料&#xff0c;终于将我的C盘容量扩充了且数据保存…

Hive 【Hive(七)窗口函数练习】

窗口函数案例 数据准备 1&#xff09;建表语句 create table order_info (order_id string, --订单iduser_id string, -- 用户iduser_name string, -- 用户姓名order_date string, -- 下单日期order_amount int -- 订单金额 ); 2&#xff09;装载语句 i…

一文搞懂APT攻击

APT攻击 1. 基本概念2. APT的攻击阶段3. APT的典型案例参考 1. 基本概念 高级持续性威胁&#xff08;APT&#xff0c;Advanced Persistent Threat&#xff09;&#xff0c;又叫高级长期威胁&#xff0c;是一种复杂的、持续的网络攻击&#xff0c;包含高级、长期、威胁三个要素…

超声波气象站——环境监测领域强大助手

超声波气象站是环境监测领域的一位强大助手&#xff0c;超声波气象站是一种综合型的气象设备&#xff0c;精巧而全面&#xff0c;满足人们对环境状况的深入了解和精准把握。 首先&#xff0c;超声波气象站的传感器部分&#xff0c;是它的核心组成部分&#xff0c;这位“感知者”…

PHP 行事准则:allow_url_fopen 与 allow_url_include

文章目录 参考环境allow_url_fopenallow_url_fopen 配置项操作远程文件file 协议 allow_url_includeallow_url_include 配置项 allow_url_include 与 allow_url_fopen区别联系默认配置配置项关闭所导致异常运行时配置ini_set()限制 参考 项目描述搜索引擎Bing、GoogleAI 大模型…

Elasticsearch数据操作原理

Elasticsearch 是一个开源的、基于 Lucene 的分布式搜索和分析引擎&#xff0c;设计用于云计算环境中&#xff0c;能够实现实时的、可扩展的搜索、分析和探索全文和结构化数据。它具有高度的可扩展性&#xff0c;可以在短时间内搜索和分析大量数据。 Elasticsearch 不仅仅是一个…

Linux 本地 Docker Registry本地镜像仓库远程连接

Linux 本地 Docker Registry本地镜像仓库远程连接 Docker Registry 本地镜像仓库,简单几步结合cpolar内网穿透工具实现远程pull or push (拉取和推送)镜像,不受本地局域网限制&#xff01; 1. 部署Docker Registry 使用官网安装方式,docker命令一键启动,该命令启动一个regis…

JVM-满老师

JVM 前言程序计数器&#xff0c;栈&#xff0c;虚拟机栈&#xff1a;本地方法栈&#xff1a;堆&#xff0c;方法区&#xff1a;堆内存溢出方法区运行时常量池 垃圾回收垃圾回收算法分代回收 前言 JVM 可以理解的代码就叫做字节码&#xff08;即扩展名为 .class 的文件&#xff…

虫情测报灯如何实现自动化测报?

一、KH-CQPest虫情测报灯的工作过程 虫情测报灯是新一代的图像式虫情测报智能设备&#xff0c;在农业虫害防治领域拥有独特魅力&#xff0c;它内置高像素的摄像头&#xff0c;能够精准记录并将照片上传至智慧农业平台识别害虫的形态、种类。虫情测报灯运用现代光电数控集成技术…

【案例】从kaggle的房价预测模型案例中了解深度学习模型,即如何学习深度学习模型

1、背景 深度学习是什么&#xff0c;为了解决什么样的问题 深度学习是一种机器学习的方法&#xff0c;它的主要目的是从数据中自动学习到有效的特征表示。深度学习通过多层的特征转换&#xff0c;把原始数据变成更高层次、更抽象的表示。这些学习到的表示可以替代人工设计的…

领域驱动设计

今天我们来聊聊领域驱动设计&#xff08;Domain Driven Design&#xff0c;即 DDD&#xff09;。 说起业务建模&#xff0c;领域驱动设计是一个绕不过去的话题。自从 Eric Evans 在2000后发布他的名著“Domain Driven Design&#xff1a;Tackling the Complexity in the Heart …

Netty(四)NIO-优化与源码

Netty优化与源码 1. 优化 1.1 扩展序列化算法 序列化&#xff0c;反序列化主要用于消息正文的转换。 序列化&#xff1a;将java对象转为要传输对象(byte[]或json&#xff0c;最终都是byte[]) 反序列化&#xff1a;将正文还原成java对象。 //java自带的序列化 // 反序列化 b…