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

Xml 依赖注入容器的好处是什么?,xml,spring,dependency-injection,Xml,Spring,Dependency Injection,我理解依赖注入本身的好处。让我们以春天为例。我还了解其他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="girlfr

我理解依赖注入本身的好处。让我们以春天为例。我还了解其他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的人都能理解。 那么依赖注入框架的主要目的是什么呢?(或显示其优点的一段代码。)


更新:
万一

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}
如果存在多个myService实现,IoC框架如何猜测我希望注入哪个myService实现?如果给定接口只有一个实现,并且我让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一些信息,它是基于它工作的——我不告诉它做什么。在spring的例子中,我的声明告诉spring要做什么——那么为什么要声明它,为什么不直接做呢


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

在.NET世界中,大多数IoC框架都提供XML和代码配置


例如,StructureMap和Ninject使用fluent接口来配置容器。您不再受限于使用XML配置文件。Spring也存在于.NET中,它严重依赖于XML文件,因为它是它的历史主配置接口,但仍然可以通过编程方式配置容器。

您不需要在每次更改配置时重新编译代码。它将简化程序部署和维护。例如,只需对配置文件进行一次更改,就可以将一个组件与另一个组件进行交换。

这是一个有点复杂的问题,但我倾向于同意,大量的xml配置并没有带来多大好处。我希望我的应用程序尽可能地减少依赖性,包括庞大的框架

mary = new FakeFemale();
IService myService;
// ...
public void doSomething() {
  myService.fetchData();
}
<bean id="jane" class="foo.bar.HotFemale">
  <property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
  <property name="girlfriend" ref="jane"/>
</bean>
UI-context.xml Model-context.xml Controller-context.xml AlternateUI-context.xml Model-context.xml Controller-context.xml ControllerAdditions-context.xml
<bean id="base" parent="RootXFireBean">
    <property name="secondProperty" ref="secondBean" />
</bean>

<bean id="secondBean" parent="secondaryXFireBean">
    <property name="firstProperty" ref="thirdBean" />
</bean>

<bean id="thirdBean" parent="thirdXFireBean">
    <property name="secondProperty" ref="myNewBean" />
</bean>

<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />
public class TheFirstPointlessClass extends SomeXFireClass {
    public TheFirstPointlessClass() {
        setFirstProperty(new TheSecondPointlessClass());
        setSecondProperty(new TheThingThatWasHereBefore());
    }
}

public class TheSecondPointlessClass extends YetAnotherXFireClass {
    public TheSecondPointlessClass() {
        setFirstProperty(TheThirdPointlessClass());
    }
}

public class TheThirdPointlessClass extends GeeAnotherXFireClass {
    public TheThirdPointlessClass() {
        setFirstProperty(new AnotherThingThatWasHereBefore());
        setSecondProperty(new WowItsActuallyTheCodeThatChanged());
    }
}

public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
    public WowItsActuallyTheCodeThatChanged() {
    }

    public overrideTheMethod(Object[] arguments) {
        //Do overridden stuff
    }
}