1前書き

このチュートリアルでは、Dagger 2(高速で軽量な依存性注入フレームワーク)を見ていきます。

このフレームワークはJavaとAndroidの両方で利用可能ですが、コンパイル時インジェクションから派生した高性能は後者のための主要なソリューションになります。


2依存性注入

ちなみに、

Dependency Injection

は、より一般的なInversion of Controlの原理を具体的に適用したものです。プログラム自体。

他のオブジェクトが必要とするオブジェクト(または依存関係)のインスタンスを提供する外部コンポーネントを通じて実装されています。

そして異なるフレームワークは異なる方法で依存性注入を実装します。特に、これらの違いの最も注目すべき点の1つは、インジェクションが実行時とコンパイル時のどちらで行われるかです。

実行時DIは通常リフレクションに基づいています。リフレクションは、使用は簡単ですが実行時は遅くなります。

実行時DIフレームワークはSpring

一方、コンパイル時DIはコード生成に基づいています。これは、すべてのヘビーウェイト操作がコンパイル中に実行されることを意味します。コンパイル時DIは複雑さを増しますが、一般的には高速に実行されます。

短剣2はこの範疇に入る。


3 Maven/Gradleの設定

プロジェクトでDaggerを使用するには、https://search.maven.org/classic/#artifactdetails%7Ccom.google.dagger%7C2.16%7Cjar[

dagger

依存関係]をプロジェクトに追加する必要があります

pom.xml

:

<dependency>
    <groupId>com.google.dagger</groupId>
    <artifactId>dagger</artifactId>
    <version>2.16</version>
</dependency>

さらに、アノテーション付きクラスを変換するために使用されるhttps://search.maven.org/classic/#artifactdetails%7Ccom.google.dagger%7Cdagger-compiler%7C2.16%7Cjar[Daggerコンパイラを含める]も必要です。注入に使用されるコードに

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
         <annotationProcessorPaths>
              <path>
                  <groupId>com.google.dagger</groupId>
                  <artifactId>dagger-compiler</artifactId>
                  <version>2.16</version>
              </path>
         </annotationProcessorPaths>
    </configuration>
</plugin>

この設定では、Mavenは生成されたコードを

target/generated-sources/annotations

に出力します。

そのため、コード補完機能を使用する場合は、おそらくIDEをさらに設定する必要があります。注釈プロセッサを直接サポートしているIDEもあれば、このディレクトリをビルドパスに追加する必要があるIDEもあります。

あるいは、GradleでAndroidを使用している場合は、両方の依存関係を含めることができます。

compile 'com.google.dagger:dagger:2.16'
annotationProcessor 'com.google.dagger:dagger-compiler:2.16'

プロジェクトにDaggerがありますので、サンプルアプリケーションを作成して動作を確認しましょう。


4実装

私たちの例では、そのコンポーネントを注入することによって自動車を造ろうとします。

さて、

Daggerは多くの場所で標準のJSR-330アノテーションを使用しています

1つは

@Inject.

です。

注釈をフィールドまたはコンストラクタに追加できます。しかし、

Daggerはプライベートフィールドへのインジェクションをサポートしていないため

、カプセル化を維持するためにコンストラクタインジェクションを使用します。

public class Car {

    private Engine engine;
    private Brand brand;

    @Inject
    public Car(Engine engine, Brand brand) {
        this.engine = engine;
        this.brand = brand;
    }

   //getters and setters

}

次に、インジェクションを実行するためのコードを実装します。具体的には、次のものを作成します。

  • a

    module

    は、を提供または構築するクラスです。

オブジェクトの依存関係

a

component ** はインジェクタを生成するために使用されるインタフェースです。

複雑なプロジェクトには複数のモジュールやコンポーネントが含まれている場合がありますが、非常に基本的なプログラムを扱っているので、それぞれ1つでも十分です。

実装方法を見てみましょう。


4.1. モジュール

モジュールを作成するには、** クラスに

@ Module

アノテーションを付ける必要があります。このアノテーションは、クラスがコンテナに対して依存関係を利用可能にできることを示します。

@Module
public class VehiclesModule {
}

次に、** 依存関係を構築するメソッドに

@ provide

アノテーションを追加する必要があります。

@Module
public class VehiclesModule {
    @Provides
    public Engine provideEngine() {
        return new Engine();
    }

    @Provides
    @Singleton
    public Brand provideBrand() {
        return new Brand("Baeldung");
    }
}

また、与えられた依存関係の範囲を設定することができます。この場合、

Brand

インスタンスにシングルトンスコープを指定して、すべてのcarインスタンスが同じブランドオブジェクトを共有するようにします。


4.2. 成分

それでは、コンポーネントインターフェイスを作成します

__。これは、

VehiclesModule__が提供する依存関係を注入して、Carインスタンスを生成するクラスです。

簡単に言うと、

Car

を返すメソッドシグネチャが必要です。** クラスに

@ Component

アノテーションを付ける必要があります。

@Singleton
@Component(modules = VehiclesModule.class)
public interface VehiclesComponent {
    Car buildCar();
}


@ Component

アノテーションの引数としてモジュールクラスを渡したことに注目してください。もしそうしなければ、ダガーは車の依存関係を構築する方法を知らないでしょう。

また、私たちのモジュールはシングルトンオブジェクトを提供しているので、私たちは自分のコンポーネントに同じスコープを与えなければなりません。


4.3. クライアントコード

最後に、注釈プロセッサを起動してインジェクタコードを生成するために

mvn compile

を実行します。

その後、インターフェイスと同じ名前で「

Dagger

」という接頭辞を付けたコンポーネント実装が見つかります。

@Test
public void givenGeneratedComponent__whenBuildingCar__thenDependenciesInjected() {
    VehiclesComponent component = DaggerVehiclesComponent.create();

    Car carOne = component.buildCar();
    Car carTwo = component.buildCar();

    Assert.assertNotNull(carOne);
    Assert.assertNotNull(carTwo);
    Assert.assertNotNull(carOne.getEngine());
    Assert.assertNotNull(carTwo.getEngine());
    Assert.assertNotNull(carOne.getBrand());
    Assert.assertNotNull(carTwo.getBrand());
    Assert.assertNotEquals(carOne.getEngine(), carTwo.getEngine());
    Assert.assertEquals(carOne.getBrand(), carTwo.getBrand());
}


5春のアナロジー

Springをよく知っている人は、2つのフレームワークの間にいくつかの類似点があることに気付いたかもしれません。

Daggerの

@ Module

アノテーションは、Springのすべてのステレオタイプアノテーションと非常によく似た方法でコンテナにクラスを認識させます(たとえば、

@ Service



@ Controller

…​)。同様に、

@ provide



@ Component

は、それぞれSpringの

@ Bean



@ Lookup

とほぼ同等です。

Springはデフォルトでシングルトンスコープを想定していますが、DaggerはデフォルトでSpring開発者がプロ​​トタイプスコープとして参照するものにデフォルト設定し、それぞれプロバイダメソッドを呼び出しているという点でもう1つの違いがあります。依存関係が必要な時。


6. 結論

この記事では、基本的な例を使ってDagger 2をセットアップして使用する方法を説明しました。実行時とコンパイル時のインジェクションの違いについても検討しました。

いつものように、この記事のすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/dagger[GitHubで利用可能]です。