构造(Constructor)注入还是设值(Setter)注入?
01 Aug 2017构造(Constructor)注入
使用构造(Constructor)注入
需要将依赖作为构造函数的参数, 由于构造函数必须被调用, 因此强制的保证了依赖的初始化, 并且也将代码的依赖管理与 Spring 解耦, 实现了容器无关.
从 Spring 4.3 开始, 在只有一个构造器的类上,
@Autowired
注解可以不需要显示指定. 这是特别优雅的, 因为它使得类将不携带任何容器注释. 基于此点, 同样从 Spring 4.3 开始,@Configuration
也开始支持构造(Constructor)注入
, 并且在单构造器的情况下不需要指定@Autowired
import javax.inject.Inject;
public class Foo {
private Bar bar;
@Inject
public Foo(Bar bar) {
this.bar = bar;
}
}
设值(Setter)注入
使用设值(Setter)注入
, setter
是否被调用具有不确定性, 因此对象实例可能永远不会得到依赖的组件. 唯一的方式是将@Autowired
或@Inject
等注解添加到setter
上, 同时也打破了容器无关性.
import javax.inject.Inject;
public class Foo {
private Bar bar;
@Inject
public void setBar(Bar bar) {
this.bar = bar;
}
}
Spring Team 推荐
由于可以将构造(Constructor)注入
和设值(Setter)注入
混合使用, 因此将构造(Constructor)注入
作为必填依赖的策略, 设值(Setter)注入
作为可选依赖的策略会是一个不错的做法. 同时, 在setter
使用@Required
注解可以将依赖变为必需的依赖.
Spring team 主张使用构造(Constructor)注入
, 因为它实现了将不可变对象作为应用组件, 从而保证了必需的依赖不能为空. 此外, 构造(Constructor)注入
组件总是会返回包含完全状态的客户端(调用端)代码. 附注一点: 大量的构造参数是一个坏的代码味道
,这意味着该类可能包含了太多的责任,应该进行重构以更好进行关注点分离。
设值(Setter)注入
应当主要用于可选依赖的管理, 这些依赖可以被赋以合理的默认值. 否则, 所有使用到该依赖的位置都要添加非空检测. 设值(Setter)注入
的好处则是setter
方法使得对象实例可以被重复配置和注入. 通过JMX
管理通过设值(Setter)注入
的依赖就是一个引人注目的方式.
对于一个特定的类需要使用最合理的依赖注入方式. 有时, 当使用第三方没有源码的类时, 选择就已经为你做好了. 例如: 如果一个第三方类没有暴露出setter
方法, 这时构造(Constructor)注入
就是唯一的选择了.