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 {spring framework扩展点
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 ⽅法注⼊:
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 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 注⼊时,推荐使⽤构造器注⼊⽅式:
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 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 提醒循环依赖。
参考:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。