Bean的哪一个定义是最佳实践?为什么?
例如,类型1可用于单元测试而无需创建上下文。
输入1
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
类型2
public class MovieRecommender {
@Autowired
public CustomerPreferenceDao customerPreferenceDao;
// ...
}
答案 0 :(得分:4)
我会说第一个。不仅仅是因为你可以轻松地测试它,而是因为一个简单的规则
在构造函数的末尾,一个对象应该具有实际执行其任务所需的everythig
(对不起,我不记得我在哪里读到它:(无论如何,我认为这是一个很好的规则)
因此,通过以第二种方式实现您的类,您可以创建不拥有所需内容的实例。您必须实例化它并设置其依赖项。如果你忘记了最后一部分会怎么样?
这就是为什么我总是推荐构造函数注入并将依赖项设置为final
,因此除非在构造函数中设置它们,否则它不会编译
答案 1 :(得分:2)
向下移动构造函数依赖注入优先于字段依赖注入:您无法将其作为常规POJO进行测试。
根据documentation扩展构造函数与Setter方法依赖注入的讨论:
[..]使用构造函数强制执行是一个很好的经验法则 依赖项和setter方法或可选的配置方法 依赖
答案 2 :(得分:1)
我会说第一个更好。
我使用它的主要原因是,设置测试更简单,更清洁。您只需创建模拟的依赖项并将其传递给正在测试的组件的构造函数。
从Spring 4.3开始,具有单个构造函数的类可以省略@Autowired
注释。
所以你可以写:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
还有一招。如果你将它与Lombok的@AllArgsConstructor
一起使用,那么你也不必编写constuctor(与字段注入相同),并且你也有测试的方便构造函数。
@AllArgsConstructor
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao; //injected
}
因此,如果您使用的是Lombok,我会使用构造函数注入+ AllArgsConstructor
。
还有一些关于这个issue的精彩文章。
答案 3 :(得分:1)
我会建议类型2
因为无论如何你正在使用注释将依赖注入类,这是通过使用 Reflection API 完成的。 ..
因此没有使用构造函数初始化...
如果您不想使用注释,请按照要求使用 -
如果要在通过setter方法创建对象后更改(初始化)值,则转到setter注入..
如果两个注入都可用,则Setter注入会覆盖使用构造函数注入初始化的属性值。
答案 4 :(得分:1)
第一个(也称为构造函数依赖注入)主要是因为它更容易测试。如果你想模拟customerPreferenceDao,你可以模拟它并将其注入MovieRecommender的一个实例。它可以让您更好地控制自己正在做的事情。