我在一些关于Spring MVC和Portlet的帖子中读到,不推荐 * 字段注入 *。正如我所理解的,field injection 是当你像这样用@Autowired
注入Bean时:
@Component
public class MyComponent {
@Autowired
private Cart cart;
}
在我的研究中,我还读到了关于 * 构造函数注入 * 的内容:
@Component
public class MyComponent {
private final Cart cart;
@Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
}
这两种注射方式的优点和缺点是什么?
**编辑1:**由于此问题被标记为this question的重复,我检查了它。因为在问题和答案中都没有任何代码示例,所以我不清楚我对我使用的注入类型的猜测是否正确。
5条答案
按热度按时间xxslljrj1#
注射类型
有三种方法可以将依赖项注入到bean中:
1.通过构造函数
1.通过setter或其他方法
1.通过反射,直接进入田地
您正在使用选项3。这就是当您直接在您的领域使用
@Autowired
时所发生的情况。注射指南
一个通用的指导原则which is recommended by Spring(参见基于构造器的DI或基于设置器的DI部分)如下所示:
现场注入缺点
不赞成现场注入的原因如下:
结论
根据您的需要,您应该主要使用构造函数注入或构造函数和setter注入的混合。现场注入有许多缺点,应该避免。字段注入的唯一优点是它更便于编写,这并不超过所有的缺点。
进一步阅读
我写了一篇关于为什么通常不推荐现场注入的博客文章:Field Dependency Injection Considered Harmful。
bjp0bcyl2#
这是软件开发中永无休止的讨论之一,但行业中的主要影响者对这个主题越来越固执己见,并开始建议构造函数注入作为更好的选择。
构造函数注入
优点:
*更好的可测试性。在单元测试中不需要任何模拟库或Spring上下文。您可以使用 new 关键字创建要测试的对象。这样的测试总是更快,因为它们不依赖于反射机制。(This question在30分钟后被问到。如果作者使用了构造函数注入,它就不会出现)。
*不变性。一旦设置了依赖关系,就无法更改它们。
*更安全的代码。在执行构造函数之后,你的对象就可以使用了,因为你可以验证任何作为参数传递的东西。对象可以是就绪的,也可以是未就绪的,两者之间没有状态。使用场注入时,当对象脆弱时引入中间步骤。
*更清晰的强制依赖表达。在这个问题上,现场注入是不明确的。
*让开发人员思考设计。dit写了一个有8个参数的构造函数,这实际上是一个糟糕的设计和the God object anti-pattern的标志。无论一个类在其构造函数中或字段中是否有8个依赖项,它总是错误的。人们更不愿意向构造函数添加比通过字段更多的依赖项。它向你的大脑发出信号,告诉你应该停下来思考一下你的代码结构。
缺点:
*更多代码(但现代IDE减轻了痛苦)。
基本上,场注入相反。
cl25kdpy3#
品味问题。这是你的决定。
但是我可以解释,为什么我从来不使用 * 构造函数注入 *。
1.我不想为所有
@Service
、@Repository
和@Controller
bean实现构造函数。我的意思是,有大约40-50个豆子或更多。每次我添加一个新的字段,我都必须扩展构造函数。不我不想也没必要1.如果您的Bean(服务或控制器)需要注入许多其他Bean,该怎么办?一个有4个以上参数的构造函数是非常丑陋的。
1.如果我使用的是CDI,那么构造函数与我无关。
编辑#1:Vojtech Ruzicka说:
类有太多的依赖项,可能违反了单一责任原则,应该重构
是的理论和现实下面是一个例子:
DashboardController
Map到单路径*:8080/dashboard
。我的
DashboardController
从其他服务收集了大量信息,并将其显示在 Jmeter 板/系统概述页面中。我需要这个控制器。所以我必须只保护这一条路径(基本身份验证或用户角色过滤器)。编辑#2:由于每个人都关注构造函数中的8个参数...这是一个真实的示例-客户遗留代码。我已经改变了同样的论证也适用于我的4+参数。
这都是关于代码注入,而不是示例构造。
bz4sfanl4#
另一条评论- Vojtech Ruzicka表示Spring以三种方式注入bean(得分最多的答案):
1.通过构造函数
1.通过setter或其他方法
1.通过反射,直接进入田地
这个答案是错误的-因为每一种注射Spring都使用反射!使用IDE,在setter / constructor上设置断点,并检查。
这可能是一个品味的问题,但也可能是一个案例的问题。@dieter提供了一个极好的情况下,现场注入更好。如果您在设置Spring上下文的集成测试中使用字段注入-类的可测试性参数也是无效的-除非您想稍后将测试写入您的集成测试;)
velaa5lx5#
我知道这是7年后的事了,但要补充Vojtech Ruzicka的回复- @Autowired on fields不会对单元测试造成问题,考虑到Mockitos
@InjectMocks
注解。