我了解依赖注入本身的好处。让我们以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一段时间了,我无法提供这样的示例。而且我可以显示单行代码,这些代码演示了休眠,dwr和其他我使用的框架的好处。
更新2:
我意识到IoC配置可以更改而无需重新编译。真的是个好主意吗?我可以理解,当有人想更改数据库凭据而无需重新编译时-他可能不是开发人员。在您的实践中,除开发人员外,其他人多久更改一次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初始化,不是吗?这意味着声明性方法不会在此处添加任何内容,是吗?
当我声明休眠映射时,我只是给休眠信息一些信息,并且它基于此信息起作用-我不告诉它怎么做。如果是春天,我的声明会告诉spring到底该做些什么-那么为什么要声明它,为什么不做呢?
最后更新:
伙计们,有很多答案告诉我有关依赖注入的知识,我知道这很好。问题是关于DI配置的目的,而不是初始化代码-我倾向于认为初始化代码更短,更清晰。到目前为止,我对问题的唯一答案是,当配置更改时,它避免了重新编译。我想我应该提出另一个问题,因为这对我来说是个大秘密,为什么在这种情况下应避免编译。