dagger2入门指南Coffee浅析

文章目录

  • Dagger2 Coffee App实现浅析
    • Component返回目标对象
    • 注入CoffeeMaker对象
    • 注入CoffeeLogger
    • 注入Heater
    • 注入Pump
    • 保证全局唯一CoffeeLogger
    • 保证Heater全局唯一
    • 注解说明
  • 完整代码

如果学dagger2有些糊涂了,不妨来点简单的提升一下信心!

Dagger2 Coffee App实现浅析

官方提供了Coffee App,演示Dagger2 使用。其内容真的有些简单,下面就简单分析一下其实现过程

Component返回目标对象

我们的目标是 完成Coffee 制作并打印制作过程。显然我们要定义Component返回CoffeeMaker && CoffeeLogger对象。

  @Component
  public interface CoffeeShop {
    CoffeeMaker maker();
    CoffeeLogger logger();
  }

注入CoffeeMaker对象

public class CoffeeMaker {
  private final CoffeeLogger logger;
  private final Lazy heater; // Create a possibly costly heater only when we use it.
  private final Pump pump;

 
  CoffeeMaker(CoffeeLogger logger, Lazy heater, Pump pump) {
    this.logger = logger;
    this.heater = heater;
    this.pump = pump;
  }

  public void brew() {
    heater.get().on();
    pump.pump();
    logger.log(" [_]P coffee! [_]P ");
    heater.get().off();
  }
}

显然,为了实现CoffeeMaker对象注入,最简单的方式在构造函数添加@Inject注解。为了符合单一原则,CoffeeMaker内部需要的CoffeeLogger、Heater、Pump都需要从外部进行注入,下面依次分析。

注入CoffeeLogger

CoffeeLogger 工具类原始代码如下:

public final class CoffeeLogger {
  private final List logs = new ArrayList<>();

  CoffeeLogger() {}

  public void log(String msg) {
    logs.add(msg);
  }

  public List logs() {
    return new ArrayList<>(logs);
  }
}

最简单的注入方式莫过于给构造函数添加@Inject注解。

注入Heater

Heater接口源码如下:

public interface Heater {
  void on();
  void off();
  boolean isHot();
}

不能直接注入接口,需要提供实现类和Module进行类型转换

public class ElectricHeater implements Heater {

  private final CoffeeLogger logger;
  private boolean heating;

  @Inject
  ElectricHeater(CoffeeLogger logger) {
    this.logger = logger;
  }

  @Override
  public void on() {
    this.heating = true;
    logger.log("~ ~ ~ heating ~ ~ ~");
  }

  @Override
  public void off() {
    this.heating = false;
  }

  @Override
  public boolean isHot() {
    return heating;
  }
}

@Module
interface HeaterModule {
  @Binds
  Heater bindHeater(ElectricHeater impl);
}

给实现类构造函数添加@Inject注解,在Module下写一个@Binds修饰的函数,参数为实现类、返回值为接口。也是可以实现的最简单的方式。

为了CoffeeShop可以使用HeaterModule,将HeaterModule添加到CoffeeShop的modules参数中。

注入Pump

public interface Pump {
  void pump();
}
public class Thermosiphon implements Pump {
  private final CoffeeLogger logger;
  private final Heater heater;

  @Inject
  Thermosiphon(CoffeeLogger logger, Heater heater) {
    this.logger = logger;
    this.heater = heater;
  }

  @Override
  public void pump() {
    if (heater.isHot()) {
      logger.log("=> => pumping => =>");
    }
  }
}

@Module
abstract class PumpModule {
  @Binds
  abstract Pump providePump(Thermosiphon pump);
}

这个和Heater注入完全一样。

保证全局唯一CoffeeLogger

这个很好理解,Heater、Pump如果都创建一个CoffeeLogger,就不可能将日志记录完整。因此将CoffeeLogger和CoffeeShop都添加上@Singleton注解。

保证Heater全局唯一

Thermosiphon.pump()中判断heater状态,如果不能保证单例,判断状态也没有任何意义。对于接口的实现方式,就只能在@Binds修饰的函数上进行添加。

注解说明

https://dagger.dev/dev-guide/

完整代码

https://gitee.com/guchuanhang/dagger2-coffee-app

你可能感兴趣的:(java,java)