@Autowired 和 private Final 哪种方法更有效?

问题描述 投票:0回答:5

我的问题很简单。哪种方法更有效? 正如我所看到的,method2 中的 DI 是更新的。但我想问你我该用哪一个?

方法一:

@Autowired
private CustomerRepository customerRepo;

方法2:

private final CustomerRepository custormerRepo;
public StudentService(CustomerRepository customerRepo) {
    this.customerRepo = customerRepo;
}
java dependency-injection inversion-of-control autowired
5个回答
10
投票

TL;DR: 方法 2 更加灵活。

方法1是字段注入的示例,方法2是构造函数注入的示例。

字段注入有一些构造函数注入可以避免的缺点。以下是构造函数注入的一些优点:

不变性:

普通 Java 无法做到这一点:

@Autowired
private final CustomerRepository customerRepo;

// No constructor that sets "customerRepo".

所以,Spring 提供了构造函数注入:

private final CustomerRepository customerRepo;

@Autowired
public StudentService(final CustomerRepository customerRepo) {
  this.customerRepo = customerRepo;
}

有时首选不变性。原因之一是它有助于线程安全。另一个是安全。

就我个人而言,我遵循的规则是“如果可以是最终的,就应该是最终的”。 编辑 23-05-23: 如果您正在编写库,则此规则没有意义,因为您希望轻松扩展和更改功能。

测试:

您不需要反射来设置依赖项。是的,许多模拟框架都会为您处理这个问题,但是通过构造函数注入,您可以选择在构造函数上调用

new

讨厌

NullPointerException

对象是通过调用其构造函数来创建的,对吗?我们通常希望参数在传入时为非空。通过构造函数注入,Spring IoC 容器确保构造函数中传递的所有参数在传递到构造函数之前都可用。


1
投票

在您的主代码中,您应该使用方法 2,因为不建议使用字段注入(方法 1)。 (原因请参见此处

在你的测试代码中,使用方法1是可以的。


1
投票

我建议你提出更好的建议。通过使用 Lombok 库的

@RequiredArgConstructor
,您可以避免样板代码。如果您想知道为什么不推荐使用
@Autowired
,因为当您想在应用程序中编写单元测试时会出现问题,那么如果您使用
@Autowired


0
投票

使用构造函数注入,Spring也推荐它


-1
投票

除了其他答案所说的关于不变性之外,构造函数注入的另一个好处是能够避免 NPE(字段未初始化)。使用自动装配,从测试中创建类,然后必须记住设置字段。使用构造函数注入,您不能不初始化该字段。这在 Kotlin 中更为突出,其中自动装配字段被声明为

lateinit var
,如果在初始化之前使用,则会抛出运行时异常。但是构造函数参数可以声明为非 null 类型,这会阻止您显式传递 null。

© www.soinside.com 2019 - 2024. All rights reserved.