依赖注入
每个基于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方法,在该方法中,我们将创建SpellChecker实例。此实例将用于调用setter方法以初始化TextEditor的属性。因此,DI存在两个主要变体,下面的两个子章节将通过示例介绍它们:
- 基于构造函数的依赖注入 - 当容器调用带有多个参数的类构造函数时,将完成基于构造函数的DI,每个参数表示对另一个类的依赖。
- 基于Setter的依赖注入 - 通过调用无参数构造函数或无参数静态工厂方法以实例化您的bean之后,容器通过在bean上调用setter方法来完成基于setter的依赖注入(DI)。
您可以混合使用基于构造函数的DI和基于Setter的DI,但这是一个很好的经验法则,对于强制性依赖项使用构造函数参数,对于可选的依赖项使用setter方法。使用DI原理,代码更清晰,当为对象提供依赖项时,解耦会更有效。该对象不查找其依赖项,也不知道依赖项的位置或类,而是Spring框架负责所有工作。