为什么我们不应该使用查找而不是依赖注入?

Why should we not use look up instead of dependency injection?

是否有任何充分的理由不在应用程序上下文中查找对象而不是“假设”注入了依赖项? 例如:

public Dependency getDependency(){
     if (dependency  == null){
        dependency = (Dependency) applicationContext.getBean("dependency");
     }
     return dependency;
}

有争议的论点

污染对象 Spring 特定对象

有些人可能会抱怨使用应用程序上下文会将实现与 Spring 内容绑定在一起。但是,创建对 applicationContext 的间接访问可以轻松解决。好的...让我举例说明:

public Dependency getDependency(){
     if (dependency  == null){
        dependency = (Dependency) serviceLocator.getBean("dependency");
     }
     return dependency;
}

难以更改实现

首先,它(依赖对象)可以在应用程序上下文中轻松更改。但是,使用通常的修改器可以直接插入模拟更容易:

public void setDependency(Dependency dep){
     this.dependency = dep;
}

历史问题

很久以前,Java 世界上的每个人都在使用服务定位器(通过称为 JNDI 的技术在目录服务中)来拥有可互换的对象基础结构。我们可以在目录服务中绑定三种对象:可序列化数据、引用或 Dircontext。它还允许您在分布式环境中查找对象。

然后,我们进行了 Spring 革命,现在大多数情况下都使用 DI(依赖注入)。

但是,Spring 并未禁止服务定位器模式。例如,使用 ApplicationContext 允许我们以服务定位器的方式查找 bean。我们可以认为 Spring 框架提供了一个带有集中配置的大型对象工厂、依赖注入工具以及一个可以轻松处理的服务目录。最后一段差点忘记了。

相关问题

Why is Spring's ApplicationContext.getBean considered bad?

我不考虑,因为这些答案虽然有启发性,但并没有启发上面提出的观点。

我个人对此的看法。 通过注释易于使用 DI 与必须通过 applicationContext 获取 bean 相比。 但归根结底,我认为主要区别在于依赖项的位置。 服务位置需要客户端代码请求相关的特定依赖项,而使用依赖项注入,容器会创建所有对象并将这些依赖项作为构造函数参数注入。 坦率地说,最终两者都是可行的,但考虑一下:据我所知,JNDI 查找在性能方面非常昂贵,因此最终建议您缓存它们。

注入的服务组件比使用服务定位器的服务组件更简单,而且更简单通常是更好的工程。使用依赖注入的 Bean 只是常规的旧 Java 对象,(有时)碰巧在构造函数上有 @Inject 注释(Spring JavaConfig bean 甚至可能不需要任何那)。该 bean 无需手动与查找代码交互,如果您需要更改传递给它的依赖项(例如,以便您可以注入模拟),管理其自身依赖项的 bean 将需要很多更多基础设施即将建成。