Dagger 2:注入具有构造函数参数的成员

时间:2018-02-02 11:06:25

标签: java dependency-injection dependencies dagger-2 dagger

我正在尝试通过实现虚拟Java控制台应用程序来学习Dagger 2,我有这个类。

public class Lemonader {

    private Water water;
    private Lemon lemon;
    private Sugar sugar;

    private WaterCooler waterCooler;

    public Lemonader(Water water, Lemon lemon, Sugar sugar) {
        this.water = water;
        this.lemon = lemon;
        this.sugar = sugar;
        this.waterCooler = new WaterCooler(water); // TODO remove hard dependency via Dagger 2
    }

    public void makeLemonade() {
        System.out.println("Making lemonade..");
        waterCooler.coolItUpTheWater();
        System.out.println("Lemonade has been made with " + water.getAmount() + " liters of water, " + sugar.getAmount() + " kilograms of sugar and " + lemon.getQuantity() + " lemons.");
    }

这就是我创建Lemonader对象

的方式
public class LemonaderHelper {

    public Lemonader getLemonader(int waterAmount, boolean isWaterHot, int lemonQuantity, int sugarAmount) {
        Water w = new Water(); 
        w.setAmount(waterAmount);
        w.setCold(isWaterHot);

        Lemon l = new Lemon(); 
        l.setQuantity(lemonQuantity);

        Sugar s = new Sugar(); 
        s.setAmount(sugarAmount);

        Lemonader lemonader = new Lemonader(w, l, s); 

        return lemonader;
    }

}

我想通过Dagger 2注入Lemonader的WaterCooler成员但我找不到通过water构造函数的Lemonader实例的方法(我尝试创建提供的模块) WaterWaterCooler。它有效,但它创建了一个新的water实例,而不是传递来自Lemonader构造函数的实例。我怎么能通过Dagger 2做到这一点?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

Dagger 2用于在图中自动提供依赖关系。因为WaterCooler只接受一个依赖关系并且它不在图中,因此使用WaterCooler作为实现细节,我完全按照你的方式使用它:

this.waterCooler = new WaterCooler(water);

但是,如果您希望能够替换实现,您可能会考虑注入相关对象,其中有一个方法需要一个参数(水)并返回冷水源。您可能会认为这只是一个构造函数包装器,但实际上它遵循factory method pattern

interface SourceOfCoolWaterFactory {
  /** Probably returns a water cooler. Might return a refrigerator. */
  SourceOfCoolWater createCoolWaterSource(Water water);
}
啊哈哈!现在您可以注入SourceOfCoolWaterFactory,并创建一个只调用new WaterCooler(water)的实现。这将删除您在代码注释中标识的硬依赖关系,允许您替换所需的任何实现 - 包括测试的模拟。重要的是,这也允许您混合图表中的依赖项,例如当您的WaterCooler耗尽电池时:

public class WaterCoolerFactory implements {
  private final Provider<Electricity> electricityProvider;

  @Inject public WaterCoolerFactory(Provider<Electricity> electricityProvider) {
    this.electricityProvider = electricityProvider;
  }

  @Override
  public SourceOfCoolWater createCoolWaterSource(Water water) { 
    return new WaterCooler(water, electricityProvider.get());
  }
}

你现在有一个可以在Dagger中绑定的实现,允许你的Lemonader注入SourceOfCoolWaterFactory而不是直接调用WaterCooler构造函数,并正确地将图形生成的依赖项如Electricity添加到构造函数依赖项中,如{{ 1}}。

尽管Dagger实际上没有提供任何自动化工厂的方法,但谷歌有一个名为AutoFactory的姐妹项目,它可以为任何JSR-330依赖注入框架生成注入工厂(例如Dagger,Guice) ,和Spring),它位于名为Google Auto的包中,用于值对象和Java服务的代码生成器。使用AutoFactory,您可以使用一些注释来注释WaterCooler,AutoFactory将创建一个可以在Dagger中绑定的实现:

Water