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

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


当前回答

针对5岁儿童的依赖注入。

当你自己去把冰箱里的东西拿出来时,你可能会引起问题。你可能会让门开着,你可能会得到妈妈或爸爸不希望你拥有的东西。你甚至可能在寻找我们甚至没有或已经过期的东西。

你应该做的是陈述一个需要,“我需要午餐时喝点东西”,然后我们会确保你坐下吃饭时有东西。

其他回答

任何非平凡的应用程序都由两个或多个类组成,它们相互协作以执行某些业务逻辑。传统上,每个对象都负责获取自己对与其协作的对象(其依赖关系)的引用。在应用DI时,对象在创建时由协调系统中每个对象的某个外部实体赋予其依赖性。换句话说,依赖项被注入到对象中。

有关详细信息,请参阅此处输入链接描述

“依赖注入”不就是指使用参数化构造函数和公共setter吗?

James Shore的文章展示了以下示例进行比较。

没有依赖注入的构造函数:公共类示例{私有数据库Thingie myDatabase;public Example(){myDatabase=新数据库Thingie();} public void doStuff(){... myDatabase.getData();... } } 具有依赖注入的构造函数:公共类示例{私有数据库Thingie myDatabase;公共示例(DatabaseThingie使用ThisDatabaseReplace){myDatabase=改用此数据库;}public void doStuff(){... myDatabase.getData();... } }

我知道已经有很多答案,但我发现这非常有用: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实例的任何类提供。

到目前为止,我找到的最好的定义是詹姆斯·肖尔的定义:

“依赖注入”是25美元5美分概念的术语。[...]依赖注入意味着对象的实例变量。[...].

马丁·福勒的一篇文章可能也很有用。

依赖注入基本上是提供对象所需的对象(其依赖项),而不是让它自己构造它们。这是一种非常有用的测试技术,因为它允许对依赖项进行嘲笑或清除。

依赖关系可以通过多种方式注入到对象中(例如构造函数注入或setter注入)。甚至可以使用专门的依赖注入框架(例如Spring)来实现这一点,但它们肯定不是必需的。您不需要这些框架进行依赖注入。显式实例化和传递对象(依赖项)与框架注入一样好。

例如,我们有两类客户机和服务。客户端将使用服务

public class Service {
    public void doSomeThingInService() {
        // ...
    }
}

无依赖注入

方式1)

public class Client {
    public void doSomeThingInClient() {
        Service service = new Service();
        service.doSomeThingInService();
    }
}

方式2)

public class Client {
    Service service = new Service();
    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

方式3)

public class Client {
    Service service;
    public Client() {
        service = new Service();
    }
    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

1) 2)3)使用

Client client = new Client();
client.doSomeThingInService();

优势

易于理解的

缺点

难以测试客户端类当我们更改Service构造函数时,我们需要在所有位置更改代码createService对象

使用依赖注入

方式1)构造函数注入

public class Client {
    Service service;

    Client(Service service) {
        this.service = service;
    }

    // Example Client has 2 dependency 
    // Client(Service service, IDatabas database) {
    //    this.service = service;
    //    this.database = database;
    // }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

使用

Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();

方式2)沉淀剂注入

public class Client {
    Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

使用

Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();

方式3)接口注入

检查https://en.wikipedia.org/wiki/Dependency_injection

===

现在,这段代码已经遵循了依赖注入,测试客户端类更容易。然而,我们仍然多次使用新的Service(),并且在更改Service构造函数时效果不佳。为了防止这种情况,我们可以使用DI注射器1) 简单手动喷油器

public class Injector {
    public static Service provideService(){
        return new Service();
    }

    public static IDatabase provideDatatBase(){
        return new SqliteDatabase();
    }
    public static ObjectA provideObjectA(){
        return new ObjectA(provideService(...));
    }
}

使用

Service service = Injector.provideService();

2) 使用库:适用于Android dagger2

优势

使测试更容易更改服务时,只需在Injector类中更改如果您使用使用构造函数注入,当您查看Client的构造函数时,您将看到Client类有多少依赖项

缺点

如果使用构造函数注入,则在创建客户端时创建服务对象,有时我们在客户端类中使用函数而不使用服务,因此创建的服务被浪费

依赖注入定义

https://en.wikipedia.org/wiki/Dependency_injection

依赖项是可以使用的对象(服务)注入是将依赖项(Service)传递给将使用它的依赖对象(Client)