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

我明白依赖注入本身的好处。 以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和我使用的其他框架的好处。


更新2:
我意识到IoC配置可以在不重新编译的情况下进行更改。 这真的是个好主意吗? 我可以理解何时有人想更改数据库凭证而不重新编译 - 他可能不是开发人员。 在您的实践中,开发人员以外的其他人更改IoC配置的频率如何? 我认为对于开发人员来说,没有必要重新编译特定的类而不是改变配置。 对于非开发人员,您可能希望简化他的生活并提供一些更简单的配置文件。


更新3:

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

有什么好做的exoutal? 你不会让所有的代码都是外部的,而你肯定可以 - 只要将它放在ClassName.java.txt文件中,即时手动读取和编译 - 哇,你避免了重新编译。 为什么要避免编译?!

您节省了编码时间,因为您声明性地提供了映射,而不是程序代码

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

控制原理的反转允许简单的单元测试,因为您可以用真实的实现替换实际的实现(例如,将SQL数据库替换为内存中的一个)

我明白控制好处的倒置(我更喜欢把这里讨论的设计模式称为依赖注入,因为IoC更通用 - 有很多种控制,而且我们只反转其中的一种 - 控制初始化)。 我在问为什么有人为了它而需要其他东西而不是编程语言。 我绝对可以使用代码替换真正的实现。 这段代码将表达与配置相同的东西 - 它只是用假值初始化字段。

mary = new FakeFemale();

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

当我声明hibernate映射时,我只是休眠一些信息,并基于它工作 - 我不告诉它该做什么。 在春天的情况下,我的声明告诉春天完全可以做 - 为什么要声明它,为什么不做呢?


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


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

  • 测试
  • 生产维护
  • 测试

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

  • 单元测试
  • 集成测试
  • 黑匣子测试
  • 您想要做的是为最后两个测试场景(Integration&Black box),不重新编译应用程序的任何部分。

    如果您的任何测试场景需要您更改配置(即:使用另一个组件来模拟银行业务集成或执行性能负载),则可以轻松处理这种情况(这可以通过配置DI端的DI端来实现虽然IoC。

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

    生产

    作为一名开发人员,您不必(也不应该)控制生产环境(特别是当您的应用程序分发给多个客户或单独的站点时),这对我来说是使用IoC和外部配置的真正好处,因为基础设施/生产支持可以调整和调整现场环境,而无需返回开发人员并通过测试(当他们想要做的是移动组件时,成本更高)。

    概要

    IoC外部配置的主要优点来自于给予其他人(非开发人员)配置应用程序的权力,根据我的经验,这仅在有限的情况下才有用:

  • 应用程序分发给环境不同的多个站点/客户端。
  • 有限的开发控制/生产环境和设置的输入。
  • 测试场景。
  • 在实践中,我发现即使在开发一些可以控制环境的东西时,它也会运行,但随着时间的推移,最好给别人改变配置的能力:

  • 开发时,你不知道什么时候会改变(应用程序非常有用,你的公司会把它卖给其他人)。
  • 我不希望在每次请求可能通过设置和使用良好配置模型进行处理的轻微更改时更改代码。
  • 注意:应用程序是指完整的解决方案(不仅仅是可执行文件),因此应用程序需要运行所有文件。


    依赖注入是一种编码风格,其根源在于观察对象委托通常比对象继承更有用的设计模式(即对象具有 - 关系比对象更有用 - 关系)。 然而,DI的其他成分对于创建对象接口的工作是必需的。 结合这两种强大的设计模式,软件工程师很快意识到他们可以创建灵活松散耦合的代码,因此依赖注入的概念诞生了。 然而,直到DI真正起飞的某些高级语言中才有了对象反射。 反射组件是当今大多数DI系统的核心,因为DI的非常酷的方面需要能够以编程方式选择对象,并使用外部系统配置并将它们注入到其他对象中,并独立于对象本身。

    语言必须为普通的面向对象编程技术提供良好的支持,并且支持对象接口和对象反射(例如Java和C#)。 虽然您可以在C ++系统中使用DI模式构建程序,但由于在语言本身中缺乏反射支持,因此无法支持应用程序服务器和其他DI平台,从而限制了DI模式的表达能力。

    使用DI模式构建系统的优势:

  • DI代码更容易重用,因为“依赖”功能被推广到定义良好的接口中,允许将由合适的应用程序平台处理的配置随意插入其他对象的独立对象。
  • DI代码更容易测试。 通过构建实现应用程序逻辑所期望的接口的“模拟”对象,可以在黑盒中测试该对象表达的功能。
  • DI代码更灵活。 这是天生松散耦合的代码 - 到极致。 这允许程序员选择和选择对象如何基于一端的必需接口和另一端的表示接口进行连接。
  • DI对象的外部(Xml)配置意味着其他人可以在不可预见的方向上自定义您的代码。
  • 外部配置也是一个关注模式的分离,因为对象初始化和对象相关性管理的所有问题都可以由应用程序服务器来处理。
  • 请注意,外部配置不需要使用DI模式,对于简单的互连,小型构建器对象通常是足够的。 两者之间存在灵活性的折衷。 构建器对象不像外部可见配置文件那样灵活。 DI系统的开发人员必须权衡灵活性与便利性之间的优势,同时注意配置文件中所述的对目标结构的小规模细粒度控制可能会增加混乱和维护成本。
  • 绝对的DI代码似乎更麻烦,将所有配置对象的XML文件注入其他对象的缺点似乎很困难。 然而,这是DI系统的重点。 通过将代码对象作为一系列配置设置进行混合和匹配,您可以使用第三方代码构建复杂的系统,并且只需最少的编码。

    这个问题中提供的例子仅仅涉及适当分解的DI对象库可以提供的表达力的表面。 通过一些练习和很多自律,大多数DI从业者发现他们可以构建对应用程序代码的测试覆盖率为100%的系统。 这一点本身就非凡。 这不是测试几百行代码的小应用程序的测试覆盖率,而是包含数十万行代码的应用程序的100%测试覆盖率。 我无法描述任何其他可提供此级别可测试性的设计模式。

    你是正确的,因为只有10几行代码的应用比几个对象加上一系列XML配置文件更容易理解。 然而,与大多数强大的设计模式一样,随着您继续向系统添加新功能,可以找到收益。

    简而言之,基于大规模DI的应用程序更易于调试和更易于理解。 虽然Xml配置不是'编译时间检查',但作者知道的所有应用程序服务如果尝试将具有不兼容接口的对象插入另一个对象,则会向开发人员提供错误消息。 并且大多数提供涵盖所有已知对象配置的“检查”功能。 通过检查待注入对象A是否实现了对象B对于所有配置的对象注入所需的接口,这很容易且快速地完成。


    这是一个加载的问题,但我倾向于认为,大量的XML配置并不会带来太大好处。 我喜欢我的应用程序尽可能轻松地依赖,包括庞大的框架。

    他们在很多时候都简化代码,但是他们在复杂性方面也有一些开销,这使得追踪问题变得相当困难(我已经看到了这样的问题,而直接的Java我会更容易处理)。

    我想这取决于风格,你喜欢什么?你喜欢飞行自己的解决方案,并有内部知道它的好处,或银行对现有的解决方案,这可能会遇到困难时,配置不是'恰到好处? 这全是一个折衷。

    但是,XML配置有点儿是我的宠儿...我不惜一切代价避免它。

    链接地址: http://www.djcxy.com/p/2313.html

    上一篇: What are the benefits of dependency injection containers?

    下一篇: Setting up a pc bluetooth server for android