当前位置: 首页 > 面试题库 >

依赖项注入容器的好处是什么?

赵永逸
2023-03-14
问题内容

我了解依赖注入本身的好处。让我们以Spring为例。我还了解其他Spring功能(如AOP,不同类型的助手等)的好处。我只是想知道XML配置的好处是什么,例如:

<bean id="Mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
  <property name="girlfriend" ref="Mary"/>
</bean>

与普通的旧Java代码相比,例如:

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

它更容易调试,检查编译时间,并且仅懂Java的任何人都可以理解。那么,依赖注入框架的主要目的是什么?(或一段显示其优点的代码。)

如果

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

如果有多个,IoC框架如何猜测要注入的myService的哪种实现?如果给定接口只有一个实现,而我让IoC容器自动决定使用它,则在出现第二个实现后,它将被破坏。而且,如果有意仅使用一种可能的接口实现,则无需注入该接口。

看到IoC的一小部分配置显示出它的好处,这将真的很有趣。我已经使用Spring一段时间了,我无法提供这样的示例。而且我可以显示单行代码,以证明hibernate,dwr和我使用的其他框架的好处。

我意识到IoC配置可以更改而无需重新编译。真的是个好主意吗?我可以理解,当有人想要更改数据库凭据而无需重新编译时-他可能不是开发人员。在你的实践中,除开发人员外,其他人多久更改一次IoC配置?我认为对于开发人员而言,无需重新编译该特定类,而无需更改配置。对于非开发人员,你可能希望使他的生活更轻松,并提供一些更简单的配置文件。

接口之间的映射及其具体实现的外部配置

使它具有延展性有什么好处?你不必将所有代码都放在外部,但可以肯定地将它放在ClassName.java.txt文件中,可以即时读取和手动进行编译-哇,你避免了重新编译。为什么要避免编译?

节省了编码时间,因为你以声明方式而不是在过程代码中提供了映射

我知道有时声明式方法可以节省时间。例如,我仅声明一次bean属性与DB列之间的映射,并且hibernate在加载,保存,基于HSQL构建SQL等情况下使用此映射。这就是声明性方法的工作原理。对于Spring(在我的示例中),声明具有更多的行,并且与相应代码具有相同的表达力。如果有这样的声明比代码短的例子-我想看一下。

“控制反转”原理使单元测试变得容易,因为你可以用假的实例替换实际的实现(例如用内存中的实例替换SQL数据库)

我确实了解控制权的倒置(我更喜欢将这里讨论的设计模式称为“依赖注入”,因为IoC更通用-有许多种控制权,而我们仅倒置其中一种-初始化控制权)。我在问为什么有人需要编程语言以外的东西。我绝对可以使用代码将真实的实现替换为假的实现。此代码将表示与配置相同的内容-它将仅使用伪值初始化字段。

mary = new FakeFemale();

我确实了解DI的好处。与配置相同功能的代码相比,我不明白外部XML配置可以带来哪些好处。我认为不应避免进行编译-我每天都在编译,但我还活着。我认为DI的配置是声明式方法的不良示例。如果声明一次,并且以不同的方式多次使用,例如hibernate cfg,则声明很有用。例如,hibernate属性cfg,其中bean属性和DB列之间的映射用于保存,加载,构建搜索查询等。SpringDI配置可以轻松转换为像在此问题开头一样配置代码,可以吗?而且它仅用于bean初始化,不是吗?这意味着声明性方法不会在此处添加任何内容,是吗?

当我声明hibernate映射时,我只是给hibernate提供一些信息,并且它基于hibernate而工作-我不告诉它怎么做。如果是春天,我的声明会告诉spring到底该做些什么-那么为什么要声明它,为什么不做呢?

伙计们,有很多答案告诉我有关依赖注入的知识,我知道这很好。问题是关于DI配置的目的,而不是初始化代码-我倾向于认为初始化代码更短,更清晰。到目前为止,我对问题的唯一答案是,当配置更改时,它避免了重新编译。我想我应该提出另一个问题,因为这对我来说是个大秘密,为什么在这种情况下应避免编译。


问题答案:

就我自己而言,使用IoC(并使用外部配置)的主要原因之一是围绕以下两个方面:

  • Testing
  • Production maintenance

Testing

如果将测试分为3个场景(在大规模开发中这是很正常的):

  • Unit testing
  • Integration testing
  • Black box testing

对于最后两个测试场景(集成和黑匣子),你需要做的是不重新编译应用程序的任何部分。

如果你的任何测试方案都要求你更改配置(即:使用另一个组件来模拟银行集成或执行性能负载),则可以轻松地进行处理(这确实是在配置服务器的DI端的好处下)。 IoC虽然。

此外,如果你的应用程序在多个站点(具有不同的服务器和组件配置)上使用,或者在实时环境中具有更改的配置,则可以使用以后的测试阶段来验证该应用程序将处理这些更改。

Production

作为开发人员,你没有(也不应该)控制生产环境(尤其是当你的应用分发到多个客户或单独的站点时),这对我来说是同时使用IoC和外部配置的真正好处,因为需要基础架构/生产支持来调整和调整实时环境,而无需回到开发人员手中并通过测试(他们只想移动一个组件就需要更高的成本)。

Summary

IoC的外部配置的主要好处来自赋予其他人(非开发人员)配置应用程序的能力,以我的经验,这仅在少数情况下才有用:

  • 应用程序分发到环境会有所不同的多个站点/客户端。
  • 对生产环境和设置的有限开发控制/输入。
  • 测试方案。

在实践中,我发现即使开发出你可以控制环境的东西,随着时间的流逝,最好还是让其他人来更改配置:

  • 开发时,你不知道它何时会更改(该应用程序非常有用,你的公司将其出售给其他人)。
  • 我不想每次都要求通过设置和使用良好的配置模型来进行轻微更改时就不得不更改代码。
    注意:应用程序指的是完整的解决方案(不仅仅是可执行文件),因此应用程序运行所需的所有文件。


 类似资料:
  • 使用。NET核心,您可以注册“服务”,据我所知,这仅仅意味着您可以将类型注册到具体的类中。 因此,我决定是时候学习和练习DI了。我理解这个概念,通过测试它是非常有益的。然而,让我困惑的是注册服务的想法以及它是否真的需要。 编辑 这个问题围绕着如何使用容器(服务)而不是为什么在构造函数中使用接口。

  • 容器和依赖注入 5.1版本正式引入了容器的概念,用来更方便的管理类依赖及运行依赖注入。 5.0版本已经支持依赖注入的,依赖注入和容器没有必然关系 容器类的工作由think\Container类完成,但大多数情况我们只需要通过app助手函数即可完成大部分操作。 依赖注入其实本质上是指对类的依赖通过构造器完成自动注入,例如在控制器架构方法和操作方法中一旦对参数进行对象类型约束则会自动触发依赖注入,由于

  • 问题内容: 已经发布了几个问题,其中包括有关依赖项注入的特定问题,例如何时使用它以及支持它的框架。然而, 什么是依赖项注入?何时/为什么/不应该使用它? 问题答案: 依赖注入 将依赖传递给其他 对象 或 框架 (依赖注入器)。 依赖注入使测试更加容易。注入可以通过 构造函数 完成。 其构造函数如下: 问题 :如果涉及复杂的任务,例如磁盘访问或网络访问,则 很难 对其进行单元测试。程序员必须进行模拟

  • 我正在使用gradle/querydsl和JPA 2.1。 我想使用APT(qenties)生成querydsl元数据。 为此,我使用了gradle apt插件和gradle 4.7 在我的项目中,我使用以下配置了compileJava选项:

  • 考虑下面的代码: 上面的代码是一个表示一个汉堡包类。 该类假设汉堡包括Bun, Patty 和 Toppings。 该类还负责制作Bun, Patty 和 Toppings。 这是一件坏事。 如果需要素食汉堡怎么办? 一个天真的方法可能是: 好吧,这有点不同,它在某些方面更灵活,但它仍然相当脆弱。 如果Patty构造函数改变以允许新的功能会发生什么? 整个汉堡包类必须更新。 事实上,任何时候任何这

  • 依赖注入(Dependency Injection,DI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象。 Martin 的文章 已经解释了 DI 容器为什么很有用。 这里我们主要讲解 Yii 提供的 DI 容器的使用方法。 依赖注入(Dependency Injection) Yii 通过 yii\di\Container 类提供 DI 容器特性。 它支持如下几种类型的依赖注入: