Spring Framework中的依赖注入:构造器注入 vs. Setter注入
前言
构造器注入和Setter注入是依赖注入(Dependency Injection,DI)中两种常见的方式,用于向一个对象注入其所依赖的其他对象或数值。这两种注入方式有各自的特点和用途。
构造器注入(Constructor Injection):
在构造器注入中,依赖关系通过类的构造函数传递。这意味着在创建对象时,依赖的对象实例会作为构造函数的参数传递进来。
示例(Java):
public class UserService {private UserRepository userRepository;// 构造器注入public UserService(UserRepository userRepository) {this.userRepository = userRepository;}// 其他方法使用userRepository
}
优点:
- 对象的依赖关系在创建时就被确定,对象一旦创建就不可变,有助于保持对象的一致性和可靠性。
- 在构造函数中明确声明依赖,可以使类的使用更加清晰,减少了后续对依赖的猜测。
Setter注入(Setter Injection):
在Setter注入中,依赖通过类的setter方法进行注入。这意味着你可以在对象创建后随时改变依赖关系。
示例(Java):
public class UserService {private UserRepository userRepository;// Setter注入public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}// 其他方法使用userRepository
}
优点:
- 灵活性高,可以在运行时动态更改依赖关系。
- 允许逐步构建对象,不需要一次性提供所有依赖。
选择构造器注入还是Setter注入取决于以下因素:
- 不变性需求: 如果对象的依赖关系在创建后不应该更改,构造器注入是一个好的选择。
- 灵活性需求: 如果对象的依赖关系可能在运行时更改,Setter注入更为合适。
- 清晰性: 构造器注入通常更容易理解,因为依赖关系在对象创建时就被确定。
- 依赖数量: 如果类有大量的依赖,构造器注入可能更清晰,而不是在构造函数中添加大量的参数。
在实践中,有时也可以使用构造器注入和Setter注入的组合,以满足不同的需求。
当前Spring Framework版本对两者的看法
Spring Framework是一个流行的Java开发框架,它提供了丰富的功能,包括依赖注入(Dependency Injection)的支持。Spring对构造器注入和Setter注入都提供了良好的支持,而且在不同版本中,它并没有显著改变对这两种注入方式的看法。当前版本Spring Framework更推荐通过构造方法注入Bean。
来自“Constructor-based or setter-based DI”
“The Spring team generally advocates constructor injection, as it lets
you implement application components as immutable objects and ensures that required dependencies are not null.
Spring团队通常提倡构造函数注入,因为它允许
将应用程序组件实现为不可变对象,并确保所需的依赖项不为空。
Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
此外,构造器注入的组件总是以完全初始化的状态返回给客户端(调用)代码。顺便说一句,大量的构造函数参数是一种不好的代码气味,这意味着类可能有太多的职责,应该重构以更好地解决适当的关注点分离问题。
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later.
Management through JMX MBeans is therefore a compelling use case for setter injection.”
Setter注入应该主要只用于可选的依赖项,这些依赖项可以在类中被分配合理的默认值。否则,必须在代码使用依赖项的任何地方执行非空检查。setter注入的一个好处是,setter方法使该类的对象可以在以后重新配置或重新注入。
因此,通过JMX MBeans进行管理是setter注入的一个引人注目的用例。”
总结
总结以上论点就是:
- 构造器注入提倡不可变性: 通过构造器注入对象,实现了对象初始化后的不可变性,同时确保所需依赖不为空。这有助于保持对象状态的稳定性。
- 构造器注入促使代码质量提升: 通过构造器注入,可以清晰地看到类的依赖关系,大量构造器参数说明当前类耦合过多、职责过多,从而促使编码者考虑是否需要重构,以提高代码质量和可维护性。
- Setter注入适用于可选依赖: Setter注入主要用于可选依赖,这些依赖可以在类内部被合理默认赋值。然而,需要注意的是,Setter注入的对象需要进行非空检查,因为它们具有可变性。
- Setter注入支持对象的动态重配置: 通过Setter注入,对象可以在运行时进行重新配置或重新注入。这使得Setter注入在JMX MBeans等需要动态管理的场景下变得特别有用。
关于我
👋🏻你好,我是Debug.c。微信公众号:种颗代码技术树 的维护者,一个跨专业自学Java,对技术保持热爱的bug猿,同样也是在某二线城市打拼四年余的Java Coder。
🏆在掘金、CSDN、公众号我将分享我最近学习的内容、踩过的坑以及自己对技术的理解。
📞如果您对我感兴趣,请联系我,
⭐️若有收获,就点个赞吧。
⛰若喜欢文中配图,请联系我,我发您原图。
相关文章:

Spring Framework中的依赖注入:构造器注入 vs. Setter注入
前言 构造器注入和Setter注入是依赖注入(Dependency Injection,DI)中两种常见的方式,用于向一个对象注入其所依赖的其他对象或数值。这两种注入方式有各自的特点和用途。 构造器注入(Constructor Injectionÿ…...

Java学习之路 —— API篇
文章目录 前言Object类2. Objects类3. 包装类4. StringBuilder和StringBuffer5. StringJoiner6. Math7. System8. JDK8开始新增的日期、时间9. Arrays10. Lambda表达式11. 方法引用 前言 其实转语言来说,语法都比较简单,花个三天就会了,但最…...

Windows下安装Anaconda5.3.1+Python3.8+TensorFlow2.13.0-CPU版本总结
Python3.8安装可以参考博文https://janus.blog.csdn.net/article/details/55274849 进行安装即可。 【1】Anaconda 清华的开源软件镜像站:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/下载,这里选择的是5.3.1版本。 然后正常安装就可以&am…...
DigitalVirt 日本 Lite VPS 测评
发布于 2023-07-18 在 https://chenhaotian.top/vps/digitalvirt-jp-lite/ 官网链接(含AFF):https://digitalvirt.com/aff.php?aff459 日本 软银 CMI,联通首选。 流媒体解锁很好,详见测试。 注意,测速…...

Ridgeline plot / 远山图 / 山脊图 怎么画?怎么优化?
工具 Origin 2022 当然,用Matlab、Python也是可以的。 颜色配置 色卡调整...

【STM32/FreeRTOS】SysTick定时器及FreeRTOS系统节拍
目录 一、SysTick定时器 1、SysTick寄存器介绍 (1)控制及状态寄存器 (2)重装载数值寄存器 (3)当前数值寄存器 2、SysTick寄存器配置函数 二、FreeRTOS中的SysTick定时器 1、SysTick配置函数及分析 …...

Vue3封装自定义指令+h()
官方install介绍 directive/myDir/index.js 定义指令 import { h, render, ref } from "vue"; const vMyDir {mounted(el, binding) {renderElement(el, binding);}, }; // inserted是Vue2的生命周期钩子,所以在Vue3项目中要使用mounted const renderEl…...

爆火的迅雷网盘推广,一手云盘app拉新推广渠道必备项目 学习资料
迅雷网盘是目前几个主流网盘拉新推广之一 都可以通过”聚量推客“申请 目前主流的为:夸克网盘拉新、uc网盘推广、迅雷网盘,但是由于阿里的原因 夸克目前不对外开放名额,需要等待,取而代之主流的云盘推广就是迅雷网盘了 聚量推客…...

Jmeter 请求返回多字段 —— 传递登录接口!
Jmeter创建JDBC请求获取登录账密,结果存储到变量中,依次传给登录接口。 1、添加JDBC Request并设置变量,获取数据库多个字段值 ①添加好JDBC Connection Configuration并做好数据库连接配置 ②导入mysql驱动jar包 ③测试计划->添加线程…...
es 7.0常用的命令
es 7.0常用的命令 es 7.0中只有索引和文档(document),没有类型(type)了。 es新建索引: 格式: PUT /索引名称 {"mappings":{"properties":{"字段名称":{"type":"字段类型"}}} }PUT 加索…...

[文件读取]lanproxy 文件读取 (CVE-2021-3019)
1.1漏洞描述 漏洞编号CVE-2021-3019漏洞类型文件读取漏洞等级⭐漏洞环境VULFOCUS攻击方式 描述: Lanproxy 路径遍历漏洞通过../绕过读取任意文件。该漏洞允许目录遍历读取/../conf/config.properties来获取到内部网连接的凭据。 1.2漏洞等级 高危 1.3影响版本 Lanproxy 1.4漏洞…...
记录一种引起 CL.exe/ C++ 编译器无任何提示直接崩溃的问题
只需定义在源文件或公共引入的头文件之中,编译必定CL.exe 退出,错误代码2,它不会产生任何语法意义上的错误提示,感兴趣的可以记录下。 引发崩溃的代码: template <typename T> class IS_CONFIG_LOADER_T_CLASS…...
【华为OD机试高分必刷题目】生理周期(C++-模拟迭代实现)
🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,高分通过! 文章目录 【华为OD机试高分必刷题目】生理周期(C++-模拟迭代实现)题目描述解题思路java题解代码代码OJ评判结果代码讲解寄语【华为OD机试高分必刷题目…...

【Vue】过滤器Filters
hello,我是小索奇,精心制作的Vue系列持续发放,涵盖大量的经验和示例,如对您有用,可以点赞收藏哈 过滤器 filters过滤器已从Vue 3.0中删除,不再支持了,这里可以作为了解进行学习 vue3要精简代码&…...

springcloud旅游网站源码
开发技术: jdk1.8,mysql5.7,idea,nodejs,vscode springcloud springboot mybatis vue 功能介绍: 用户端: 登录注册 首页显示搜索景区,轮播图,旅游攻略列表 点击攻…...
Unity中关于Lerp()方法的使用
在Unity中,Lerp()方法用于在两个值之间进行线性插值。 它的语法有: public static float Lerp(float a, float b, float t);//在两个float类型的值a和b之间进行线性插值 public static Vector2 Lerp(Vector2 a, Vector2 b, float t);//在两个Vector2类…...

计算机毕业设计选题推荐-体育赛事微信小程序/安卓APP-项目实战
✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...
Android BottomSheetDialog中列表滑动冲突问题
前言 使用BottomSheetDialog弹窗时,里面嵌套了一个纵向的RecyclerView,弹出后加载列表数据,发现弹窗不能滑动,产生了滑动冲突。 一、使用步骤 1.布局示例 代码如下(示例): <androidx.appco…...

sql查询查看数据库空间使用情况
SELECT UPPER(F.TABLESPACE_NAME) "表空间名", D.TOT_GROOTTE_MB "表空间大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),990.99) || % "使…...
算法分析与设计考前冲刺 (算法基础、数据结构与STL、递归和分治、 动态规划、贪心算法、 回溯算法)
算法分析与设计考前冲刺 算法基础 算法是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。 程序是算法用某种程序设计语言的具体的 具体实现 算法特征: 有穷性(有限步) 确定性 输入 输出 可行性(有限时间) 算法的复杂性&#…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...