用Dagger理解Java中的依赖注入

用Dagger理解Java中的依赖注入,java,dependency-injection,dagger-2,Java,Dependency Injection,Dagger 2,我熟悉传统设计模式中的依赖倒置原则,在传统设计模式中,您有一个抽象产品,它在请求工厂方法的类中执行任务。但依赖注入的不同之处在于它使用注释来生成产品 我正在回顾这个例子。这就是最终结果: // CoffeeApp.java public class CoffeeApp { @Singleton @Component(modules = { DripCoffeeModule.class }) public interface Coffee { CoffeeMaker maker

我熟悉传统设计模式中的依赖倒置原则,在传统设计模式中,您有一个抽象产品,它在请求工厂方法的类中执行任务。但依赖注入的不同之处在于它使用注释来生成产品

我正在回顾这个例子。这就是最终结果:

// CoffeeApp.java
public class CoffeeApp {
  @Singleton
  @Component(modules = { DripCoffeeModule.class })
  public interface Coffee {
    CoffeeMaker maker();
  }

  public static void main(String[] args) {
    Coffee coffee = DaggerCoffeeApp_Coffee.builder().build();
    coffee.maker().brew();
  }
}

$ java -cp ... coffee.CoffeeApp
~ ~ ~ heating ~ ~ ~
=> => pumping => =>
 [_]P coffee! [_]P
我很难理解这句话:

 CoffeeMaker maker();
在CoffeeMaker类中,没有make方法。那么这是如何工作的呢

这是我的理解:

CoffeeMaker类在其构造函数中使用@Inject注释:

@Inject CoffeeMaker(Lazy<Heater> heater, Pump pump) {
  this.heater = heater;
  this.pump = pump;
}
这是否意味着当调用@Inject CoffeeMaker构造函数时,它会依次发现pump引用并搜索PumpModule@Module,然后发现providePump并实例化一个新的热虹吸泵类型?

@Donato,你是对的,CoffeeMaker没有maker方法,咖啡界面确实有maker方法。该方法生成器返回CoffeMaker类型的对象。因此,在您的示例中,daggerOffeeApp_Coffee.builder.build;将返回Coffee的一个实现,该实现反过来实现maker方法

问:但请求是什么意思

我的回答:请求意味着注入,即无论你在哪里看到@Inject。例如,下面的私有变量声明请求CoffeeMaker的一个实例

咖啡机依次请求一个实例或加热器和一个泵实例:

因此,在实例化或注入maker时,将实例化并注入加热器实例和泵实例

问题:这是否意味着当调用@Inject CoffeeMaker构造函数时,它会依次发现pump引用并搜索PumpModule@Module,然后发现providePump并实例化热虹吸类型的新泵

我的回答是:没错

Dagger是一种编译时依赖项注入解决方案

界面CoffeeApp.Coffee上的CoffeeMaker行(按原样注释)表示Dagger将生成并编译CoffeeApp.Coffee的实现,该实现具有maker方法的实现,该方法将为您提供一个完全注入的CoffeeMaker实例。如果您愿意,您可以查看Dagger生成的文件DaggerOffeeApp_Coffee.java,它看起来很像上面的实现。幻灯片35和36显示了相应的工厂/提供商实现

这将迫使Dagger在咖啡机实例化时实例化一个新加热器和一个新泵,对吗

是的,通常。尽管您有权在@Provides方法中返回现有实例,或者使用@Singleton之类的注释让Dagger管理现有实例,但Dagger的默认行为是为每个依赖项创建一个新实例,并为该依赖项的每个依赖项创建一个新实例,依此类推

这是否意味着当调用@Inject CoffeeMaker构造函数时,它会依次发现pump引用并搜索PumpModule@Module,然后发现providePump并实例化热虹吸类型的新泵

您几乎是正确的:为了实现该实现,Dagger将检查@Inject CoffeeMaker构造函数,发现咖啡机需要加热器和泵,等等。对于像Guice这样的框架,这一切都发生在运行时,但对于Dagger,所有的分析和映射都发生在编译时。在您的示例中,@Provides Pump方法存在于DripOffeeModule中,Dagger不会搜索该方法:该示例通过CoffeeApp.Coffee上的@Component注释提供该方法。

请参阅组件中maker方法的解释
The method’s return type defines which dependency it satisfies.
public MyClass {
  @Inject private CoffeeMaker maker;
  ...
}
@Inject CoffeeMaker(Lazy<Heater> heater, Pump pump) {
  this.heater = heater;
  this.pump = pump;
}