6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

からくりAdvent Calendar 2019

Day 6

Dagger2についてメモ

Last updated at Posted at 2019-05-30

Dagger2とは

依存性注入フレームワークのこと。

内容

自身の理解のために、公式ページの以下の内容を荒く訳してます。
https://dagger.dev/users-guide.html

  • Declaring Dependencies
  • Satisfying Dependencies
  • Building the Graph

@Injectアノテーションについて

Daggerがクラスのインスタンスを作成するために使用するコンストラクタに@Injectアノテーションを付与する。新しいインスタンスが要求される際に、Daggerは要求されたパラメータを取得し、このコンストラクタを呼ぶ。

Thermosiphon.java
class Thermosiphon implements Pump {
  private final Heater heater;

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

  ...
}

Daggerは@Injectが付いたフィールド変数に直接注入する。
この例では、フィールド変数のheater、pumpにHeaterインスタンスとPumpインスタンスを注入する。

CoffeeMaker.java
class CoffeeMaker {
  @Inject Heater heater;
  @Inject Pump pump;

  ...
}

@Provides@Moduleについて

デフォルトでは、Daggerは要求された型のインスタンスを構築することで各依存関係を満たす。
しかし、@Injectはどこでも使えるわけでない。

  • インタフェースは構築できない
  • サードパーティのクラスはアノテーションを付与できない
  • 設定可能(Configurable)なオブジェクトは設定していなくてはいけない

これらのケースでは@Providesアノテーションを付与されたメソッドを使う。
返り値の型は依存関係を満たすものを定義する。
例えば、provideHeater()はHeaterが要求された時に呼ばれる。

@Provides static Heater provideHeater() {
  return new ElectricHeater();
}

@Providesメソッドは自身が依存関係を持つことを可能にする。
以下は、Pumpを要求された時にThermosiphonを返すメソッド。

@Provides static Pump providePump(Thermosiphon pump) {
  return pump;
}

全ての@Providesメソッドはモジュールに所属しなければならない。
モジュールとは@Moduleアノテーションを付与したクラスのこと。

DripCoffeeModule.java
@Module
class DripCoffeeModule {
  @Provides static Heater provideHeater() {
    return new ElectricHeater();
  }

  @Provides static Pump providePump(Thermosiphon pump) {
    return pump;
  }
}

@Componentについて

@Inject@Providesが付与されたクラスは、それらの依存関係がリンクされたオブジェクトのグラフを形成する。
アプリケーションのメインメソッドやAndroidアプリケーションのようなコードを呼び出すものは、明確に定義された一連のルートを介してグラフにアクセスする。
Dagger2では、その一連は引数を持たないメソッドを持つインターフェースによって定義され、望む型を返す。そのようなインターフェースに対して@Componentアノテーションを付与し、modulesパラメータに対して必要なモジュールクラスを渡す。
Dagger2はそのインターフェースを実装する。

@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
  CoffeeMaker maker();
}

その実装はDaggerの接頭辞を持つインタフェースと同じ名前を持つ。
実装上ではbuilder()メソッドを呼ぶことでインスタンスを取得し、返されたbuilderを使い、依存関係をセットし、新しいインスタンスをビルドする。

CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();

デフォルトコンストラクタでアクセスできる全てのモジュールはもし何も設定されていなければビルダーが自動的にインスタンスを構築するので削除できる。
モジュールの@Providesメソッドが全て静的なら、その実装はインスタンスを全く必要としない。
もし、ユーザーが依存関係インスタンスを作成することなく、全ての依存関係が構築できるなら、生成された実装にはcreate()メソッドが用意される。これを使用し、ビルダーを処理せず新しいインスタンスを取得できる。

CoffeeShop coffeeShop = DaggerCoffeeShop.create();

CoffeeAppは注入されたCoffeeMakerを取得するためにCoffeeShopのDaggerに生成された実装を使用できる。

CoffeeApp.java
public class CoffeeApp {
  public static void main(String[] args) {
    CoffeeShop coffeeShop = DaggerCoffeeShop.create();
    coffeeShop.maker().brew();
  }
}

グラフが構築され、エントリポイントが注入されたので、Coffee Maker Appが実行できる。

$ java -cp ... coffee.CoffeeApp
~ ~ ~ heating ~ ~ ~
=> => pumping => =>
 [_]P coffee! [_]P

以上です。

6
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?