SpringBoot 构造器注入、Setter方法注入和Field注入对比
0. 引入
今天在看项目代码的时候发现在依赖注入的时候使用了构造器注入,之前使用过 Field 注入和 Setter 方法注入,对构造器注入不是很了解。经过查阅资料看到,Spring 推荐使用构造器注入的方式,下面介绍构造器注入到底有什么玄机。
1. 常见的三种注解注入方式对比
Field 注入
@Controller
public class HelloController {
@Autowired
private AlphaService alphaService;
@Autowired
private BetaService betaService;
}
field 注入方式是使用最多的,原因是这种方式使用起来非常简单,代码更加简洁。
Setter 方法注入
@Controller
public class HelloController {
private AlphaService alphaService;
private BetaService betaService;
@Autowired
public void setAlphaService(AlphaService alphaService) {
this.alphaService = alphaService;
}
@Autowired
public void setBetaService(BetaService betaService) {
this.betaService = betaService;
}
}
在 Spring 3.x 刚推出的时候,Spring 官方在对比构造器注入和 Setter 注入时,推荐使用 Setter 方法注入:
Spring 3.x Constructor-based or setter-based DI?
The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.
Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.
意思是说,当出现很多注入项的时候,构造器参数可能会变得臃肿,特别是当参数时可选的时候。Setter 方式注入可以让类在之后重新配置和重新注入;
Constructor 注入
@Controller
public class HelloController {
private final AlphaService alphaService;
private final BetaService betaService;
@Autowired
public HelloController(AlphaService alphaService, BetaService betaService) {
this.alphaService = alphaService;
this.betaService = betaService;
}
}
Spring 4.x 的时候,Spring 官方在对比构造器注入和 Setter 注入时,推荐使用构造器注入方式:
Spring 4.x Constructor-based or setter-based DI?
The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not
null. Furthermore constructor-injected components are always returned to 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.
因为使用构造器注入方式注入的组件不可变,且保证了需要的依赖不为 null。此外,构造器注入的组件总是能够在完全初始化的状态返回给客户端(调用方);对于很多参数的构造器说明可能包含了太多了职责,违背了单一职责原则,表示代码应该重构来分离职责到合适的地方。
2. 构造器注入还是 Setter 注入?
在对比 Setter 方法注入和 构造器注入的时候 分别引用的 Spring 官方文档的第二段阐述了除推荐方式的另一种方式的特点。
在 Spring 3.x 的时候 Spring 推荐 Setter 方法注入,第二段表示:一些纯粹主义者喜欢基于构造函数的注入。提供所有对象依赖项意味着对象总是在完全初始化状态下返回给客户机(调用)代码。缺点是对象不太容易重新配置和重新注入。
在 Spring 4.x 的时候 Spring 推荐构造器注入,第二段表示:Setter 注入应该主要用于可选的依赖项,这些依赖项可以在类中分配合理的默认值。否则,必须在代码使用依赖项的任何地方执行非空检查。setter 注入的一个好处是,setter 方法使该类的对象能够在以后重新配置或重新注入。
Setter 注入应该被用于可选依赖项。当没有提供它们时,类应该能够正常工作。在对象被实例化之后,依赖项可以在任何时候被更改。
构造器注入有利于强制依赖。通过在构造函数中提供依赖,您可以确保依赖对象在被构造时已准备好被使用。在构造函数中赋值的字段也可以是final的,这使得对象是完全不可变的,或者至少可以保护其必需的字段。
构造器注入还可以避免 Field 注入的循环依赖问题,比如 在 Alpha 中注入 Beta,又在 Beta 中注入 Alpha。如果使用构造器注入,在 Spring 启动的时候就会抛出 BeanCurrentlyInCreationException 提醒循环依赖。
参考:
https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/
SpringBoot 构造器注入、Setter方法注入和Field注入对比的更多相关文章
- Spring 基于设值函数(setter方法)的依赖注入
当容器调用一个无参的构造函数或一个无参的静态 factory 方法来初始化你的 bean 后,通过容器在你的 bean 上调用设值函数,基于设值函数的 DI 就完成了. 下述例子显示了一个类 Text ...
- Java学习笔记(十七):构造器和setter方法选用
- Spring官网阅读(二)(依赖注入及方法注入)
上篇文章我们学习了官网中的1.2,1.3两小节,主要是涉及了容器,以及Spring实例化对象的一些知识.这篇文章我们继续学习Spring官网,主要是针对1.4小节,主要涉及到Spring的依赖注入.虽 ...
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring DI(依赖注入)的实现方式属性注入和构造注入
依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念. 当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的 ...
- Java开发学习(七)----DI依赖注入之自动装配与集合注入
一.自动配置 上一篇博客花了大量的时间把Spring的注入去学习了下,总结起来就两个字麻烦.麻烦在配置文件的编写配置上.那有更简单方式么?有,自动配置 1.1 依赖自动装配 IoC容器根据bean所依 ...
- Spring第六弹—-依赖注入之使用构造器注入与使用属性setter方法注入
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中. 使用构造器注入 1 2 3 4 <constructor-arg index=“0” type=“java.lang. ...
- 哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入?
你两种依赖方式都可以使用,构造器注入和Setter方法注入.最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖.
- Spring-Context之六:基于Setter方法进行依赖注入
上文讲了基于构造器进行依赖注入,这里讲解基于Setter方法进行注入.在Java世界中有个约定(Convention),那就是属性的设置和获取的方法名一般是:set+属性名(参数)及get+属性名() ...
- spring构造函数注入、setter方法注入和接口注入
Spring开发指南中所说的三种注入方式: Type1 接口注入 我们常常借助接口来将调用者与实现者分离.如: public class ClassA { private InterfaceB clz ...
随机推荐
- Pass Infrastructure基础架构(下)
Pass Infrastructure基础架构(下) pass注册 PassRegistration该类在示例中简要显示了各种pass类型的定义 .该机制允许注册pass类,以便可以在文本pass管 ...
- vue3.0 props
.orange { color: rgba(255, 165, 0, 1) } Vue3.0 props 1.你是否遇到了,引用props数据报错的问题? 在Vue3.0中,采用了proxy,让很多数 ...
- 10个有趣又能编译为JavaScript的语言,你用过哪些?
现代应用相比普通的网页有不同的要求.但是浏览器是一个有着一套(大部分)固定可用的技术的平台,JavaScript依然是web应用的核心语言:任何需要在浏览器上跑的应用都需要使用这种语言. 我们都知道J ...
- noip2013 总结
转圈游戏 题目 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从0 到 n-1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,-- ...
- Mysql优化_第十三篇(HashJoin篇)
Mysql优化_第十三篇(HashJoin篇) 目录 Mysql优化_第十三篇(HashJoin篇) 1 适用场景 纯等值查询,不能使用索引 等值查询,使用到索引 多个join条件中至少包含一个等值查 ...
- HTTP首部字段详解
HTTP首部字段详解 在HTTP/1.1规范中定义了47种首部字段,总共分为四大类: 通用首部字段 -- 请求报文和响应报文两方都会使用的首部 请求首部字段 -- 从客户端向服务器端发送请求报文时使用 ...
- Linux常用命令详解下
Linux常用命令详解 目录 一.Linux常用命令 1.1.查看及切换目录(pwd.cd.ls.du) 1.2.创建目录和文件(mkdir.touch.ln) 1.3.复制.删除.移动目录和文件(c ...
- 微软官方 Win 11 “体检工具”太烂了?开发者自己做了一个
1.Win 10 免费升级到 Win 11 最近微软官方终于宣布了 Windows 11,不仅带来了全新的 UI,而且还有很多新功能:比如支持 Android 应用. 虽然微软官方已说明 Win 10 ...
- .NET Core/.NET5/.NET6 开源项目汇总9:客户端跨平台UI框架
系列目录 [已更新最新开发文章,点击查看详细] .NET Core 实现了跨平台,支持在 Windwos.Linux.macOS上开发与部署,但是也仅限于Web应用程序.对于Windows桌面 ...
- 13、ssh跳板机
13.1.前提条件: 1.跳板机服务器和其它服务器建立了ssh秘钥登录: 2.目前的环境: (1)各服务器上都建立了lc用户,并给于sudo (lc ALL= NOPASSWD:ALL )权限,lc就 ...