已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
当前回答
摘自《扎实的Java开发人员:Java 7和多语言编程的关键技术》一书
DI是IoC的一种特殊形式,因此查找依赖项的过程是不受当前执行代码的直接控制。
其他回答
到目前为止,我找到的最好的定义是詹姆斯·肖尔的定义:
“依赖注入”是25美元5美分概念的术语。[...]依赖注入意味着对象的实例变量。[...].
马丁·福勒的一篇文章可能也很有用。
依赖注入基本上是提供对象所需的对象(其依赖项),而不是让它自己构造它们。这是一种非常有用的测试技术,因为它允许对依赖项进行嘲笑或清除。
依赖关系可以通过多种方式注入到对象中(例如构造函数注入或setter注入)。甚至可以使用专门的依赖注入框架(例如Spring)来实现这一点,但它们肯定不是必需的。您不需要这些框架进行依赖注入。显式实例化和传递对象(依赖项)与框架注入一样好。
这是我见过的关于依赖注入和依赖注入容器的最简单的解释:
无依赖注入
应用程序需要Foo(例如控制器),因此:应用程序创建Foo应用程序调用FooFoo需要Bar(例如服务),因此:Foo创建BarFoo调用Bar酒吧需要Bim(服务、存储库,…),因此:条形图创建Bim酒吧有点事
使用依赖注入
应用程序需要Foo,需要Bar,需要Bim,因此:应用程序创建Bim应用程序创建Bar并赋予它Bim应用程序创建Foo并给它Bar应用程序调用FooFoo调用Bar酒吧有点事
使用依赖注入容器
应用程序需要Foo,因此:应用程序从容器中获取Foo,因此:容器创建Bim容器创建Bar并赋予它Bim容器创建Foo并给它Bar应用程序调用FooFoo调用Bar酒吧有点事
依赖注入和依赖注入容器是不同的:
依赖注入是一种编写更好代码的方法DI容器是帮助注入依赖项的工具
您不需要容器来执行依赖注入。然而,容器可以帮助您。
简单来说,依赖注入(DI)是消除不同对象之间的依赖关系或紧密耦合的方法。依赖注入为每个对象提供一个内聚行为。
DI是国际奥委会春季原则的实施,该原则说“不要打电话给我们,我们会打电话给你”。使用依赖注入程序员不需要使用new关键字创建对象。
对象一旦加载到Spring容器中,我们就可以在需要时重用它们,方法是使用getBean(StringbeanName)方法从Spring容器中获取这些对象。
公认的答案是一个好答案——但我想补充一点,DI非常像代码中避免硬编码常量的经典做法。
当您使用诸如数据库名称之类的常量时,您可以将其从代码内部快速移动到某个配置文件,并将包含该值的变量传递到需要它的位置。这样做的原因是,这些常量通常比代码的其他部分更频繁地更改。例如,如果您想在测试数据库中测试代码。
在面向对象编程的世界中,DI与此类似。那里的值而不是常量文字是整个对象-但是将创建它们的代码从类代码中移出的原因是相似的-对象的更改比使用它们的代码更频繁。一个重要的情况是需要进行这样的改变,那就是测试。
依赖注入是解决“依赖混淆”需求的一种可能方案。依赖性混淆是一种将“明显”性质从向需要依赖性的类提供依赖性的过程中去除的方法,因此在某种程度上混淆了向所述类提供所述依赖性。这不一定是坏事。事实上,通过混淆向类提供依赖项的方式,类外部的某个东西负责创建依赖项,这意味着在各种情况下,可以向类提供不同的依赖项实现,而不需要对类进行任何更改。这对于在生产和测试模式之间切换非常有用(例如,使用“模拟”服务依赖)。
不幸的是,糟糕的部分是,有些人认为你需要一个专门的框架来进行依赖性混淆,如果你选择不使用特定的框架来做,那么你在某种程度上就是一个“低级”程序员。另一个非常令人不安的神话是,依赖性注入是实现依赖性混淆的唯一方法。这显然是历史性的,显然是100%错误的,但你很难说服一些人,依赖项注入可以替代依赖项混淆需求。
多年来,程序员们已经了解了依赖性混淆的需求,在考虑依赖性注入之前和之后,许多替代解决方案都已经发展起来。有工厂模式,但也有许多使用ThreadLocal的选项,其中不需要对特定实例进行注入-依赖关系被有效地注入到线程中,这样做的好处是使对象(通过方便的静态getter方法)可用于任何需要它的类,而无需向需要它的类别添加注释并设置复杂的XML“粘合”以实现这一点。当持久性需要依赖项(JPA/JDO或其他)时,它允许您更容易地实现“跨持久性”,并且域模型和业务模型类完全由POJO组成(即没有特定于框架的/锁定在注释中的)。