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 ...
随机推荐
- 如何挑选深度学习 GPU?
如何挑选深度学习 GPU? 深度学习是一个对计算有着大量需求的领域,从一定程度上来说,GPU的选择将从根本上决定深度学习的体验.因此,选择购买合适的GPU是一项非常重要的决策.那么2020年,如何选择 ...
- TorchScript神经网络集成技术
TorchScript神经网络集成技术 create_torchscript_neuropod 将TorchScript模型打包为neuropod包. create_torchscript_neuro ...
- 【问题记录】—SignalR连接断线重连
起因: ASP.NET Core SignalR是一个开源库,可简化向应用添加实时 SignalR Web 功能. 实时 Web 功能使服务器端代码能够立即将内容推送到客户端.(相信大家都用得比较多了 ...
- powerDisigner使用
最近要忙期考,但还是决定每天抽点空来写CodeSmith的系列文章了,在此实在不敢用教程这个词语,毕竟自己对CodeSmith了解的也不是很多,有很多牛人都在博客园发布了不少关于CodeSmith ...
- 三、Tomcat配置文件的介绍
*允许直接复制另外多份完整的tomcat数据,修改配置保证不冲突,起多个tomcat,优点:其中一个tomcat挂了不影响其他网页 tomcat配置文件server.xml介绍 <Server& ...
- JDK并发包一
JDK并发包一 同步控制是并发程序必不可少的重要手段,synchronized是一种最简单的控制方法.但JDK提供了更加强大的方法----重入锁 重入锁 重入锁使用java.util.concurre ...
- cisco交换机端口从errdisable状态恢复
故障描述 经用户反馈,一台cisco2960x接入交换机的一个端口插网线不通,ip电话也没有poe供电. 排查过程 查看交换机端口状态,发现变成了errdisable: ZH_HQN_SW2960X_ ...
- html中各种标签和属性(最基础的基本都有)
1.标题标签: h1~h6 ctrl+1~6 2.段落标签: p ctrl+shift+p 3.换行标签: br shift+回车 4.水平线: hr 5.加粗标签: stro ...
- Redis短结构
本章将介绍3种非常有价值的降低Redis内存占用的方法.降低Redis的内存占用有助于减少创建快照和加载快照所需的时间.提升载入AOF文件和重写AOF文件时的效率.缩短从服务器进行同步所需的时间,并且 ...
- 4、nfs服务器的搭建
4.1.nfs服务介绍: samba服务器一般互联网企业不会使用 nfs服务的端口是不固定的,需要先启动rpc服务对nfs服务端口进行注册 4.2.安装nfs: rpm -qa nfs-utils r ...