我理解依赖注入本身的好处。让我们以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();
}如果有多个myService,那么myService框架如何猜测要注入哪个实现呢?如果给定接口只有一个实现,并且我让IoC容器自动决定使用它,那么在出现第二个实现后,它就会中断。如果有意地只有一个接口的可能实现,那么您就不需要注入它。
看到IoC的一小块配置将是非常有趣的,这显示了它的好处。我使用Spring已经有一段时间了,我不能提供这样的例子。我可以显示一行代码,这些行演示了hibernate、dwr和我使用的其他框架的优点。
更新2:
我意识到IoC配置可以在不重新编译的情况下进行更改。这真的是个好主意吗?我可以理解什么时候有人想要更改DB凭证而不重新编译-他可能不是开发人员。在您的实践中,开发人员以外的其他人多久更改一次IoC配置?我认为对于开发人员来说,并不需要重新编译特定的类,而不是改变配置。对于非开发人员,您可能希望使他的生活更轻松,并提供一些更简单的配置文件。
更新3:
接口及其具体实现之间映射的外部配置
有什么能让它伸直的?并不是所有的代码都是外部的,当然可以--只要把它放在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映射时,我只是给hibernate一些信息,并且它是基于hibernate工作的--我没有告诉它该做什么。如果是春天,我的声明会告诉春天该怎么做--那么为什么不直接宣布呢?
最后更新:
伙计们,很多答案都告诉我依赖注入,我知道这很好。问题在于DI配置的目的,而不是初始化代码--我倾向于认为初始化代码更短、更清晰。到目前为止,我对问题的唯一回答是,当配置发生变化时,它可以避免重新编译。我想我应该发布另一个问题,因为这对我来说是个大秘密,为什么在这种情况下应该避免编译。
发布于 2008-10-08 12:20:02
对于我自己来说,使用IoC (并使用外部配置)的主要原因之一是围绕以下两个方面:
测试
如果将测试分为3种场景(这在大规模开发中是相当正常的):
对于最后两个测试场景(Integration&Black box),您要做的是不重新编译应用程序的任何部分。
如果您的任何测试方案要求您更改配置(即:使用另一个组件来模拟银行集成,或执行性能负载),则可以很容易地处理这一点(不过,这是配置IoC的DI端的好处之一)。
此外,如果您的应用程序在多个站点(具有不同的服务器和组件配置)使用,或者在活动环境中具有更改的配置,则可以使用测试的后期阶段来验证应用程序是否会处理这些更改。
生产
作为一名开发人员,您不(也不应该)控制生产环境(特别是当您的应用程序被分发到多个客户或单独的站点时),这对我来说是使用IoC和外部配置的真正好处,因为这取决于基础设施/生产支持来调整和调整活动环境,而无需返回开发人员并通过测试(当他们只想移动组件时,成本就会更高)。
摘要
IoC的外部配置的主要好处在于让其他人(非开发人员)能够配置您的应用程序,在我的经验中,只有在有限的情况下才有用:
在实践中,我发现,即使在开发您确实可以控制环境的东西时,随着时间的推移,最好还是让其他人拥有更改配置的能力:
注意:应用程序是指完整的解决方案(不仅仅是可执行的),所以应用程序运行所需的所有文件。
发布于 2008-09-25 08:21:37
依赖注入是一种编码风格,其根源在于观察到对象委托通常比对象继承更有用的设计模式(即对象具有--关系比对象更有用--关系)。然而,DI的另一个要素是必需的,即创建对象接口。将这两种强大的设计模式结合在一起,软件工程师很快就意识到他们可以创建灵活、松散耦合的代码,从而产生了依赖注入的概念。然而,直到对象反射在某些高级语言中可用之后,DI才真正兴起。反射组件是当今大多数DI系统的核心,因为DI真正酷的方面要求能够通过编程方式选择对象,并使用与对象本身无关的系统配置对象并将它们注入其他对象。
语言必须提供对普通面向对象编程技术的良好支持,以及对对象接口和对象反射(例如Java和C#)的支持。虽然您可以在C++系统中使用DI模式构建程序,但由于语言本身缺乏反射支持,因此无法支持应用服务器和其他DI平台,从而限制了DI模式的表现力。
使用DI模式构建的系统的优点:
当然,DI代码看起来更麻烦,让所有那些将对象配置为注入其他对象的XML文件的缺点似乎是很困难的。然而,这是DI系统的重点。您的能力,混合和匹配的代码对象作为一系列的配置设置,允许您构建复杂的系统使用第三方代码,与您的部分最低限度的编码。
问题中提供的示例仅仅触及了一个适当因素的DI对象库所能提供的表现力。通过一些实践和大量的自律,大多数DI实践者发现他们可以构建具有100%测试覆盖率的应用程序代码的系统。这一点本身就是非同寻常的。这不是一个包含几百行代码的小型应用程序的100%测试覆盖率,而是包含数十万行代码的应用程序的100%测试覆盖率。我无法描述提供此级别可测试性的任何其他设计模式。
您是正确的,因为只有10行代码的应用程序比几个对象和一系列XML配置文件更容易理解。但是,与大多数功能强大的设计模式一样,当您继续向系统添加新功能时,会发现这些优点。
简而言之,大规模的基于DI的应用程序既易于调试,又易于理解。虽然Xml配置不是“编译时检查”,但如果开发人员试图将具有不兼容接口的对象注入到另一个对象,那么作者所知道的所有应用程序服务都将向开发人员提供错误消息。而且大多数都提供了包含所有已知对象配置的“检查”功能。这是通过检查待注入对象A是否实现了对象B为所有配置的对象注入所需的接口来实现的。
发布于 2008-09-25 07:44:53
这是一个有点加载的问题,但我倾向于认为,大量的xml配置并没有带来多大的好处。我希望我的应用程序尽可能轻于依赖关系,包括庞大的框架。
它们在很大程度上简化了代码,但它们的复杂性也使跟踪问题变得相当困难(我亲眼目睹过这样的问题,而直接的Java处理则要舒服得多)。
我想这取决于你的风格,你对什么感到舒服.您喜欢自己的解决方案,并从中获益,还是依赖现有的解决方案,而这些解决方案在配置不正确时可能会被证明是困难的?这都是一种权衡。
然而,XML配置有点像我的宠物.我不惜一切代价去避免它。
https://stackoverflow.com/questions/131975
复制相似问题