我的问题很简单。哪种方法更有效? 正如我所看到的,method2 中的 DI 是更新的。但我想问你我该用哪一个?
方法一:
@Autowired
private CustomerRepository customerRepo;
方法2:
private final CustomerRepository custormerRepo;
public StudentService(CustomerRepository customerRepo) {
this.customerRepo = customerRepo;
}
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 容器确保构造函数中传递的所有参数在传递到构造函数之前都可用。
在您的主代码中,您应该使用方法 2,因为不建议使用字段注入(方法 1)。 (原因请参见此处)
在你的测试代码中,使用方法1是可以的。
我建议你提出更好的建议。通过使用 Lombok 库的
@RequiredArgConstructor
,您可以避免样板代码。如果您想知道为什么不推荐使用@Autowired
,因为当您想在应用程序中编写单元测试时会出现问题,那么如果您使用@Autowired
。
使用构造函数注入,Spring也推荐它
除了其他答案所说的关于不变性之外,构造函数注入的另一个好处是能够避免 NPE(字段未初始化)。使用自动装配,从测试中创建类,然后必须记住设置字段。使用构造函数注入,您不能不初始化该字段。这在 Kotlin 中更为突出,其中自动装配字段被声明为
lateinit var
,如果在初始化之前使用,则会抛出运行时异常。但是构造函数参数可以声明为非 null 类型,这会阻止您显式传递 null。