我理解依赖注入本身的好处。以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的人理解呢?那么依赖注入框架的主要目的是什么呢?(或者展示其优点的代码片段。)
UPDATE:
对于...
IService myService;// ...
public void doSomething() {
myService.fetchData();
}
如果有多个myService的实现,IoC框架如何猜测我想注入哪个?如果只有一个给定接口的实现,并且我让IoC容器自动决定使用它,那么当第二个实现出现时,就会出现问题。如果有意只有一种可能的接口实现,那么就不需要注入它。展示IoC的配置小片段,这将显示其好处。我已经使用Spring一段时间了,但我无法提供这样的示例。我可以展示单行代码,演示我使用的其他框架(如Hibernate,DWR等)的好处。
我意识到IoC配置可以在不重新编译的情况下更改。这真的是个好主意吗?我可以理解有人希望在不重新编译的情况下更改数据库凭据 - 他可能不是开发人员。在您的实践中,有多少人会更改IoC配置而不是开发人员?我认为对于开发人员来说,重新编译那个特定的类而不是更改配置并没有太大的工作量。对于非开发人员,您可能希望让他们的生活更轻松,并提供一些更简单的配置文件。
外部配置接口和它们的具体实现之间的映射是怎么回事?你不会使所有的代码都外部化,尽管你肯定可以 - 只需将它放在ClassName.java.txt文件中,手动读取和编译 - wow,你避免了重新编译。为什么要避免编译?
您提供映射声明后,节省编码时间,而不是在过程式代码中进行显式的映射。我理解有时候声明性方法可以节省时间,例如,我只在一个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配置的目的,而不是初始化代码——我倾向于认为初始化代码更短、更清晰。
到目前为止我得到的唯一回答是,它避免了在配置更改时重新编译。我想我应该发布另一个问题,因为对于我来说,为什么在这种情况下应该避免编译还是个大谜团。