Spring Dependency Injection 简明教程

Spring Dependency Injection

每个基于 Java 的应用程序都有一些对象可以协同工作,以展示最终用户所看到的工作应用程序。在编写复杂的 Java 应用程序时,应用程序类应尽可能独立于其他 Java 类,以增加重用这些类并使其独立于其他类进行单​​元测试的可能性。依赖注入(或有时称为连接)有助于将这些类粘合在一起,同时又保持它们独立性。

考虑您有一个包含文本编辑器组件的应用程序,并且您希望提供拼写检查。您的标准代码将如下所示 −

public class TextEditor {
   private SpellChecker spellChecker;

   public TextEditor() {
      spellChecker = new SpellChecker();
   }
}

我们在此处所做的是创建 TextEditor 和 SpellChecker 之间的依赖关系。在控制反转场景中,我们改为执行类似以下操作 −

public class TextEditor {
   private SpellChecker spellChecker;

   public TextEditor(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }
}

在这里,TextEditor 不应该担心 SpellChecker 实现。SpellChecker 将被独立实现,并在 TextEditor 实例化时提供给 TextEditor。此整个过程由 Spring 框架控制。

在此,我们从 TextEditor 中删除了全部控制权,并将其保存在其他地方(即 XML 配置文件),并且依赖项(即类 SpellChecker)正在通过 Class Constructor 注入到类 TextEditor 中。因此,依赖注入(DI)已经“反转”了控制流,因为您实际上已经将依赖委托给某个外部系统。

注入依赖关系的第二种方法是通过 TextEditor 类的 Setter Methods ,我们将在其中创建 SpellChecker 实例。此实例将用于调用 setter 方法来初始化 TextEditor 的属性。

因此,DI 以两种主要形式存在,以下两个小章节将用示例介绍它们 −

Sr.No.

依赖注入类型及说明

1

Constructor-based dependency injection 基于构造函数的 DI 是当容器用多个参数(每个参数都表示对另一个类的依赖)调用类构造函数时完成的。

2

Setter-based dependency injection 基于 setter 的 DI 是当容器在调用无参数构造函数或无参数静态工厂方法以实例化您的 Bean 之后,在您的 Bean 上调用 setter 方法时完成的。

您可以混合使用基于构造函数的 DI 和基于 setter 的 DI,但一个好经验法则是对强制依赖关系使用构造函数参数,对可选依赖关系使用 setter。

使用 DI 原则的代码更简洁,当对象获得其依赖项时,解耦将更加有效。对象不会查找其依赖项,并且不知道依赖项的位置或类,而是 Spring 框架负责所有操作。

Constructor Based V/s Setter Based Dependency Injection.

基于构造函数和基于 setter 的依赖注入之间有少许值得注意的区别。

  1. Granular control − 在一个构造函数接受多个值的情况下,我们需要在 Bean 配置期间传递所有值,而在使用 setter 的情况下,我们可以在特定的 setter 方法中传递值,并且可以不对其他 setter 进行配置。

  2. Setter Overrides Constructor − 在同时使用基于构造函数和基于 setter 的注入的情况下,基于 setter 的注入优先。

  3. Flexibility − Setter 方法不会像构造函数那样创建一个新的 Bean 实例,并且其值也可以更改。