构造函数注入与字段注入

Constructor injection vs Field injection

注入任何服务时,我有两个选择:

字段注入:

 @Inject 
 private MyService myService;

构造函数注入:

private MyService myService; 

@Inject
public ClassWhereIWantToInject(MyService mySerivce){
    this.myService = myService;
}

为什么构造函数注入字段注入好?

做类似的事情(我假设您正在使用 spring-boot 或与您的 CDI 类似的东西)

public class ClassWhereIWantToInject{

    private MyService myService; 

    @Inject
    public ClassWhereIWantToInject(MyService mySerivce){
        this.myService = myService;
    }
}

在这个相关的 question 中,有一些有效的论据说明为什么要使用通过构造函数注入而不是通过字段注入。它归结为一个优点,即您也可以在非 CDI 环境(即单元测试)中通过构造函数使用初始化,而无需添加更复杂的逻辑。

如果包含此注入的class将被框架注入(spring/ejb/cdi),则字段注入将被正确执行,否则(class将被调用者实例化使用 new 运算符)这实际上是一个等待发生的 NullPointerException。在这种情况下,最好使用构造函数注入。

我们可以执行可靠的字段注入,当注入将在框架注入的 class 中进行时。

我发现字段注入只有两个缺点。

  • 在测试对象时很难注入模拟。 (可以用 Mockito 的 @InjectMocks 解决)

  • 循环依赖。如果 bean A 依赖于 bean B 而 bean B 需要 bean A。如果你有构造函数注入,很容易找到它。

阅读这篇优秀的 post (https://blog.marcnuri.com/field-injection-is-not-recommended/) 我们可以更好地解释为什么 Field Injection 不是一个好的选择。

它不允许我们使用 final 关键字使字段 不可变

也离SRP单一职责原则)更远了一步,一旦Class有了这个字段开始对第三方的初始化时间有一些责任类。