已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,

什么是依赖注入,何时/为什么应该或不应该使用它?


当前回答

我知道已经有很多答案,但我发现这非常有用:http://tutorials.jenkov.com/dependency-injection/index.html

无相关性:

public class MyDao {

  protected DataSource dataSource = new DataSourceImpl(
    "driver", "url", "user", "password");

  //data access methods...
  public Person readPerson(int primaryKey) {...}     
}

附属国:

public class MyDao {

  protected DataSource dataSource = null;

  public MyDao(String driver, String url, String user, String password) {
    this.dataSource = new DataSourceImpl(driver, url, user, password);
  }

  //data access methods...
  public Person readPerson(int primaryKey) {...}
}

注意DataSourceImpl实例化是如何移动到构造函数中的。构造函数接受四个参数,即DataSourceImpl所需的四个值。虽然MyDao类仍然依赖于这四个值,但它本身不再满足这些依赖关系。它们由创建MyDao实例的任何类提供。

其他回答

让我们想象一下,你想去钓鱼:

没有依赖注入,你需要自己处理所有的事情。你需要找一艘船,买一根鱼竿,寻找诱饵等等。当然,这是可能的,但这给你带来了很多责任。在软件方面,这意味着你必须对所有这些东西进行查找。通过依赖注入,其他人负责所有准备工作,并为您提供所需的设备。你将收到(“被注射”)船、鱼竿和鱼饵——所有这些都准备好使用。

依赖注入是与Spring框架相关概念的核心。在创建任何项目的框架时,Spring都可能发挥重要作用,而依赖注入就是其中之一。

实际上,假设在java中,您创建了两个不同的类,即类A和类B,并且无论类B中有什么函数,您都希望在类A中使用,所以此时可以使用依赖注入。在这里,您可以将一个类的对象放入另一个类中,就像您可以将整个类注入另一个类别中以使其可访问一样。通过这种方式可以克服依赖性。

依赖注入只是将两个类粘合在一起,同时保持它们的分离。

依赖注入意味着一种方式(实际上是任何方式),代码的一部分(例如类)可以以模块化的方式访问依赖项(代码的其他部分,例如它所依赖的其他类),而不必对它们进行硬编码(因此它们可以自由更改或重写,甚至可以根据需要在其他时间加载)

(顺便说一句,是的,对于一个相当简单的概念,它已经成为一个过度炒作的25美元的名字),我的25美分

依赖注入是一种实践,它使解耦的组件与它们的一些依赖不可知,这遵循SOLID准则

依赖反转原则:一个人应该“依赖于抽象,而不是结核。

依赖注入的更好实现是Composition Root设计模式,因为它允许组件与依赖注入容器分离。

我再次推荐这篇关于作文根的伟大文章http://blog.ploeh.dk/2011/07/28/CompositionRoot/作者:Mark Seemann

本文的要点如下:

合成根是应用程序中的(最好)唯一位置其中模块被组合在一起。

...

只有应用程序应该具有合成根。图书馆和框架不应该。

...

DI容器只能从合成根引用。所有其他模块都不应引用容器。

Di Ninja(依赖注入框架)的文档是一个很好的例子,可以演示组合根和依赖注入的原理是如何工作的。https://github.com/di-ninja/di-ninja正如我所知,是javascript中唯一实现Composition Root设计模式的DiC。

依赖注入是将依赖传递给其他对象或框架(依赖注入器)。

依赖注入使测试更容易。注入可以通过构造函数完成。

SomeClass()的构造函数如下:

public SomeClass() {
    myObject = Factory.getObject();
}

问题:如果myObject涉及诸如磁盘访问或网络访问之类的复杂任务,则很难在SomeClass()上进行单元测试。程序员必须模拟myObject,并可能拦截工厂调用。

替代解决方案:

将myObject作为参数传入构造函数

public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

myObject可以直接传递,这使得测试更容易。

一种常见的替代方法是定义一个不做任何事情的构造函数。依赖注入可以通过setter完成。(h/t@MikeVella)。Martin Fowler记录了第三种选择(h/t@MarcDix),其中类显式地实现了程序员希望注入的依赖项的接口。

在没有依赖注入的情况下,很难在单元测试中隔离组件。

2013年,当我写下这个答案时,这是谷歌测试博客的一个主要主题。这对我来说仍然是最大的优势,因为程序员在运行时设计中并不总是需要额外的灵活性(例如,服务定位器或类似模式)。程序员通常需要在测试期间隔离类。