Spring依赖注入Bean类型的8种情况详解

news2024/11/24 9:38:35

1、普通对象

这没什么好说的,大家都这么用的,比如需要用到 UserService,直接 @Autowired 就可以了。

@Autowired
private UserService userService;

2、Collection 及其子接口

除了支持注入一个单一的对象之外,@Autowired 还支持注入一个 Collection 对象。

比如说,现在有个消息通知的接口MessageNotifier

这种接口一般都会有不同的实现,比如说通过邮件通知,或者 app,短信等等,所以就有多种实现,此时如果需要注入MessageNotifier,就可以使用注入 Collection 的方式,比如

@Autowired
private List<MessageNotifier> messageNotifiers;

不过这种方式有个规定,那就是注入的类型必须是 Collection 及其子接口,如果你直接注入一个ArrayList,那么此时是不支持的。

3、数组

同理,@Autowired 可实现了注入一个数组的功能。

@Autowired
private MessageNotifier[] messageNotifiers;

代码如下:

4、Map

同样的,@Autowired 还可以注入一个 Map。

@Autowired
private Map<String, MessageNotifier> messageNotifierMap;

此时注入的 map,key 的类型就是 bean 的名称,这种方式可以配合策略模式使用。

不过,这种方式只支持注入的是 Map 接口,不支持子类型接口,代码如下。

5、@Lazy

当一个注入的字段加了 @Lazy 注解之后,那么此时就代表这个字段是延迟注入。

@Autowired
@Lazy
private MessageNotifier messageNotifier;

延迟注入并不是不注入,而是注入目标对象类型的代理对象,真正的目标是当需要用到的时候在创建。

如图所示,当注入的MessageNotifier时加了 @Lazy 注解,那么此时注入的其实是MessageNotifier的代理对象,而真正的MessageNotifier对象并没有创建,图中代理对象我称为MessageNotifierProxy

由于注入的是对象是代理对象MessageNotifierProxy,那么真正被使用的就是MessageNotifierProxy,一旦调用了MessageNotifierProxy的方法,此时MessageNotifierProxy会去 Spring 容器中查找真正的MessageNotifier对象,然后再调用MessageNotifier对象的方法。

代码如下:

这就是 @Lazy 延迟注入的原理。并不是不注入,而是注入一个代理对象,可以理解为一个占位符,一个空壳子,先占着位置,等用到这个壳子的时候,这个壳子会去查找到真正的对象,调用真正对象的方法。

@Lazy 的一个使用场景就是用来解决 Spring 无法处理的循环依赖场景,比如使用了 @Async 注解的循环依赖的场景

6、Optional

Optional 是 JDK1.8 提供的一个 api,可以优雅的解决判空的问题。

@Autowired 也支持了注入 Optional 类型。

@Autowired
private Optional<MessageNotifier> messageNotifier;

代码如下:

注入 Optional 这种方式可以解决注入的对象不存在的导致异常问题,也就是安全注入。

比如说,MessageNotifier这个对象 Spring 容器中并没有,如果直接注入,此时会抛NoSuchBeanDefinitionException异常

而直接通过注入 Optional 的方式就可以解决这个问题。

除了通过 Optional 的方式之外,也可以直接把 @Autowired 的required的属性设置为 false 来解决注入对象不存在的问题。

那 Optional 存在的作用是啥?

其实 Optional 的作用仅仅是不用写为空的判断,这也是 Optional 这个类的作用作用,除了这个,跟直接 @Autowired 对象并没有其它区别。

注入 Optional 这种方式其实用的不多,在我的映像中,我在源码中几乎没有看见这种注入方式。

7、ObjectFactory 和 ObjectProvider

ObjectFactory 和 ObjectProvider 是 Spring 提供的两接口

ObjectFactory

ObjectProvider 继承了 ObjectFactory

ObjectProvider

@Autowired 也可以直接注入这两个接口。

@Autowired
private ObjectFactory<MessageNotifier> messageNotifierObjectFactory;
@Autowired
private ObjectProvider<MessageNotifier> messageNotifierObjectProvider;

代码如下:

从这段代码也可以看出,最终注入的其实是DependencyObjectProvider实现。

ObjectFactory 也是用来做延迟注入的操作,跟 @Lazy 作用差不多,但是实现原理不一样。

用上面的例子来说,注入 ObjectFactory 的时候并有创建 MessageNotifier 对象。

当需要使用 MessageNotifier 的时候需要通过 ObjectFactory 的 getObject 方法获取,此时才会真正创建 MessageNotifier 对象。

MessageNotifier messageNotifier = messageNotifierObjectFactory.getObject();

getObject 实现如下

getObject

所以 @Async 注解导致的循环依赖异常不仅可以通过 @Lazy 注解解决,也可以通过注入 ObjectFactory 的方式解决。

同理,ObjectProvider 也有延迟注入的功能,但是除了延迟注入之外,ObjectProvider 额外提供了跟 Optional 安全注入的功能,这个功能 ObjectFactory 是没有的。

上面的例子中,当使用 ObjectFactory 的 getObject 方法时,如果 Spring 容器中不存在 MessageNotifier 对象,此时也会抛NoSuchBeanDefinitionException异常。

但是 ObjectProvider 额外提供的 getIfAvailable 方法就支持获取不存在的对象的功能,当通过 getIfAvailable 获取的对象不存在时,只会返回 null,并不会出抛异常。

getIfAvailable 方法

对比一下与 getObject 方法的实现,就是在获取对象的时候是否要求对象获取的对象不是必须的,这样获取不到就不会抛异常了。

ObjectFactory 和 ObjectProvider 在框架内部中使用的还是比较多的。

就比如说,在 MybatisPlus 自动装配的时候就大量使用 ObjectProvider

并且泛型类型就是数组或者是集合,跟前面说的都对应上了。

通过这种方式就可以安全的注入,当 Spring 容器有这些对象的时候 MybatisPlus 就使用这些,没有也不会报错。

8、JSR-330 Provider

首先,来讲一下什么是 JSR-330。

JSR 是 Java Specification Requests 的缩写,是一种 Java 标准规范。

而 330 算是一个版本,除了 330,听到的比较多的还有 250。

这个规范定义了一些 IOC 的注解,我们熟知的比如 @Resource、@PostConstruct、@PreDestroy 注解都是 JSR-250 中提出的。

一些 IOC 的框架会基于这个标准来实现这些接口的功能,比如 Spring、Dagger2 等 IOC 框架都实现了这些注解的功能。

所以,如果你不使用 Spring 框架,使用其它的 IOC 框架,那么 @Resource、@PostConstruct、@PreDestroy 注解都是可以生效的。

在 JSR-330 中,提出了javax.inject.Provider这个接口

不过,想使用 JSR-330 这个接口,需要引入依赖

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

Spring 也支持注入这个类型的接口

这个接口的功能跟前面提到的 ObjectFactory 功能是一样的,也支持延迟注入的功能。

总结

到这 Spring 能够注入的 Bean 的 8 种类型就讲完了,其实这 8 种类型可以分为以下几种功能:

  • 单一注入,就是注入一个单一的对象

  • 集合注入,可以注入数组或者集合

  • 延迟注入,比如 @Lazy、ObjectFactory、ObjectProvider、JSR-330 Provider

  • 安全注入,不存在不会抛异常,比如 Optional、ObjectProvider

这几种方式并不是互斥的,比如说延迟注入也可以注入的是一个集合,前面举的 MyBaisPlus 自动装配时 ObjectProvider 的使用就是很好的例子。

同时虽然本文举例的是 @Autowird 注解和字段注入的方式,但上面提到的注入的 Bean 类型跟使用注解和注入方式没什么关系,@Resource 注解,构造器注入,setter 注入都是一样的。

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

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

相关文章

100天精通Golang(基础入门篇)——第16天:深入解析Go语言包的使用和包管理

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

java微信公众号新建草稿并发布

java实现公众号发起新建草稿&#xff0c;并且发布得到文章链接首先要先去微信公众号的设置与开发–基础设置 查看公众号的各个参数&#xff0c;这里我是存储到数据库&#xff0c;方便后期使用&#xff0c;实体类如下&#xff1a; Data public class WeChatOfficial {private st…

蛙色Web3D编辑器全面更新,会员能力解析

导语&#xff1a; 在数字化时代&#xff0c;创意设计和虚拟展示成为了营销领域的关键。然而&#xff0c;传统的创作方式往往需要复杂的软件和技术支持&#xff0c;给用户带来了诸多麻烦。 幸运的是&#xff0c;蛙色Web3D编辑器作为一款领先的在线编辑工具&#xff0c;通过全面…

Sentieon | 每周文献-Epidemiology-第五期

流行病学系列文章-1 标题&#xff08;英文&#xff09;&#xff1a;Rare Variants in Inborn Errors of Immunity Genes Associated With Covid-19 Severity标题&#xff08;中文)&#xff1a;与Covid-19严重程度相关的免疫基因先天性缺陷的罕见变异发表期刊&#xff1a;《Fron…

背包问题学习笔记

笔记&#xff0c;不是博客&#xff0c;所以就只是粗略的写写 背包问题状态设置 1.小于等于某值&#xff0c;一般用于求在限制背包体积内的情况求解 状态设置 F(n) 表示此时的背包体积小于等于n&#xff0c;F数组初始化为0即可 例题&#xff1a;423. 采药 - AcWing题库 2.恰…

用Python采用Modbus-Tcp的方式读取485电子水尺数据

README.TXT 2023/6/15 V1.0 实现了单个点位数据通信、数据解析、数据存储 2023/6/17 V2.0 实现了多个点位数据通信、数据解析、数据存储 2023/6/19 V2.1 完善log存储&#xff0c;仅保留近3天的log记录&#xff0c;避免不必要的存储&#xff1b;限制log大小&#xff0c;2MB。架…

C#生成类库dll以及调用实例

本文讲解如何用C#语言生成类库并用winform项目进行调用 目录 创建C#类库项目 Winform调用dll 创建C#类库项目 编写代码 using System.Threading;namespace ClassLibrary1 {public class Class1{private Timer myTimer = null;//定义定时器用于触发事件//定义公共的委托和调…

HW5300V3-ISCSI存储运维,看这一篇就够了01——流程图

一、存储使用流程图 二、块存储-配置流程图

【Hippo4j源码的方式安装部署教程】

&#x1f680; 线程池管理工具-Hippo4j &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#…

Vue3 + Ts + Vite —— 项目封装使用交互式 彩屑纷飞 示例 (亲测可用、复制即展示)

目录 &#x1fa82; 演示 &#x1f6f9; 目录树 &#x1f414; 安装 &#x1f916; global.d.ts &#x1f637; zkConfettiCanvas.vue &#x1f30d; confetti.ts &#x1f38b; confettiIndex.ts &#x1f637; index.vue &#x1f970;&#x1f609; 谢谢观看 &…

哪款蓝牙耳机通话清楚,几款拥有通话降噪技术的骨传导耳机分享

嘿&#xff0c;你是音乐爱好者吗&#xff1f;还是热衷于锻炼身体&#xff1f;那么你一定不能错过骨传导耳机&#xff01;这种神奇的耳机通过骨头的振动来传递声音&#xff0c;绝不同于传统的耳道或鼓膜传播方式。你可保持对周围环境的警觉&#xff0c;同时避免对你的听力造成任…

【雕爷学编程】Arduino动手做(149)---MAX9814咪头传感器模块5

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

【unity实战】手搓一个网格放置功能,及装修建造种植功能(2d3d通用,附源码)

文章目录 前言开始项目和素材1. 素材来源2. 开始项目包&#xff08;两种选择一种下载导入即可&#xff09; 开始1. 修改鼠标指针显示2. 给鼠标对应的平面位置绑定对应的指示器3. 使用Shader Graph创建网格可视化3. 网格的大小缩放和颜色控制4. 优化5. 扩展说明5.1 我们就可以通…

总结:WEB流量劫持

一、背景 在整理WEB鉴权与登陆等技术的时候&#xff0c;会涉及到安全&#xff0c;而鉴权登陆不安全有个很大的可能就是流量被劫持了。 本篇文章主要是想弄明白黑客是怎么劫持的。 二、WEB流量劫持是如何做到的&#xff1f; WEB流量劫持是指黑客将受害者的网页请求重定向到攻…

python appium UI 自动化测试框架讨论

目录 前言&#xff1a; 框架共性总结 Auto_Analysis 权限弹窗识别 前言&#xff1a; Python Appium UI自动化测试框架是一种用于测试移动应用程序的工具&#xff0c;它结合了Python编程语言和Appium测试框架的功能。 框架共性总结 1 自动找设备 连接设备 2 自动启 appium …

Java设计模式之行为型-状态模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析 五、总结 一、基础概念 状态模式允许一个对象在其内部状态改变时改变它的行为&#xff0c;对象看起来似乎修改了它的类&#xff0c;状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况&a…

有必要买apple pencil吗?ipad pencil替代品

苹果的电容笔与一般的电容笔有什么不同&#xff1f;事实上&#xff0c;从外观上来看&#xff0c;两者并没有太大的区别。唯一不同的是&#xff0c;苹果电容笔的重量更大&#xff0c;笔尖内部有专门的重力感应器&#xff0c;可以感应到重力压感对线条的影响。因此苹果的这个产品…

MongoDB复制集

文章目录 一、介绍1、存在的意义和作用&#xff1f;2、需要实现啥功能&#xff1f;3、典型案例4、注意事项 二、搭建1、安装MongoDB&#xff0c;配置环境变量2、创建数据目录3、配置文件4、启动 MongoDB 进程5、配置复制集6、验证 三、写策略writeConcern1、w参数2、j参数2.1 介…

《如何使用思维导图进行知识结构的建立和扩展》

I.思维导图作为知识管理工具的重要性 思维导图是一款强大的效率工具&#xff0c;可以帮助有效的管理知识。”一图胜千言“它用图形的方式&#xff0c;将各个主题连接起来。我们可以清晰的了解到各主题之间的关系。 在知识管理中&#xff0c;通过创建一个知识主题的中心&#xf…

PVE虚拟化平台之安装Ubuntu-server系统

PVE虚拟化平台之安装Ubuntu-server系统 一、Ubuntu介绍1.1 Ubuntu简介1.2 Ubuntu版本1.3 ubuntu命名规则 二、上传镜像到PVE存储2.1 检查PVE环境2.2 上传镜像 三、创建虚拟机3.1 设置虚拟机名称3.2 操作系统设置3.3 系统设置3.4 磁盘设置3.5 cpu设置3.6 内存设置3.7 网络设置3.…