究竟什么是现场注入以及如何避免它?

新手上路,请多包涵

我在一些关于 Spring MVC 和 Portlets 的文章中读到不推荐使用 _字段注入_。据我了解, 字段注入 是当您使用 @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: 由于这个问题被标记为 这个问题 的重复,我检查了它。因为在问题和答案中都没有任何代码示例,我不清楚我的猜测是否正确,我正在使用哪种注入类型。

原文由 T. Jung 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 633
2 个回答

注射类型

对于如何将依赖项注入到 bean 中,有三个选项:

  1. 通过构造函数
  2. 通过setter或其他方法
  3. 通过反射,直接进入字段

您正在使用选项 3。这就是当您直接在您的字段上使用 @Autowired 时发生的情况。


注射指南

Spring 推荐的 一般准则(参见 Constructor-based DISetter-based DI 部分)如下:

  • 对于强制依赖或以不变性为目标时,请使用构造函数注入
  • 对于可选或可变依赖项,使用 setter 注入
  • 在大多数情况下避免现场注入

现场注入的缺点

现场注入不被认可的原因如下:

  • 你不能像构造函数注入那样创建不可变对象
  • 您的类与您的 DI 容器紧密耦合,不能在其外部使用
  • 没有反射就无法实例化您的类(例如在单元测试中)。您需要 DI 容器来实例化它们,这使您的测试更像集成测试
  • 您真正的依赖项是从外部隐藏的,并且不会反映在您的界面中(构造函数或方法)
  • 拥有十个依赖项真的很容易。如果您使用构造函数注入,您将有一个带有十个参数的构造函数,这表明某些东西是可疑的。但是您可以无限期地使用字段注入来添加注入字段。有太多的依赖关系是一个危险信号,该类通常会做不止一件事,并且可能违反单一职责原则。

结论

根据您的需要,您应该主要使用构造函数注入或构造函数和设置器注入的某种组合。现场注入有很多缺点,应该避免。字段注入的唯一优点是写起来更方便,并没有超过所有的缺点。


进一步阅读

我写了一篇关于为什么通常不建议使用字段注入的博客文章: Field Dependency Injection Considered Harmful

原文由 Vojtech Ruzicka 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是软件开发中永无止境的讨论之一,但行业中的主要影响者对这个话题越来越有意见,并开始建议将构造函数注入作为更好的选择。

构造函数注入

优点:

  • 更好的可测试性。在单元测试中不需要任何模拟库或 Spring 上下文。您可以使用 new 关键字创建要测试的对象。这样的测试总是更快,因为它们不依赖于反射机制。 ( 这个问题 是30分钟后问的,如果作者使用构造函数注入就不会出现)。
  • 不变性。一旦设置了依赖项,它们就不能更改。
  • 更安全的代码。执行构造函数后,您的对象就可以使用了,因为您可以验证作为参数传递的任何内容。对象可以准备好也可以不准备好,中间没有状态。使用字段注入,您可以在对象易碎时引入一个中间步骤。
  • 强制依赖项的更清晰的表达。字段注入在这件事上是模棱两可的。
  • 让开发人员思考设计。上面写了一个有 8 个参数的构造函数,这实际上是糟糕设计和 上帝对象反模式 的标志。不管一个类在其构造函数中还是在字段中是否有 8 个依赖项,它总是错误的。与通过字段相比,人们更不愿意向构造函数添加更多依赖项。它向你的大脑发出信号,告诉你应该停下来思考一下你的代码结构。

缺点:

  • 更多代码(但现代 IDE 减轻了痛苦)。

基本上,场注入是相反的。

原文由 Daniel Olszewski 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题