Android+Guice その2

※2012・10 こちらのページにまとめるようにしてみました。

前回は準備編だったので今回はテスト編。簡単にInjectしてみる。

まずはInterfaceを定義する。この実装をGuiceを使ってClientにInjectする感じです。

public interface Service {
    public String getResponse(String message);
}

続いてServiceの実装。 入力されたメッセージに対して琉球弁で挨拶します。

public class ServiceImpl implements Service {
    @Override
    public String getResponse(String message) {
        return "ハイサイ!" + message;
    }
}

続いてサービスを利用する側Consumer。Clientクラス。
@Injectというアノテーションを利用するのでcom. google.inject.InjectをImportして、Injector側で注入して欲しいFieldには@Injectをつけておく。

import com.google.inject.Inject;

public class Client {
    @Inject
    private Service service;

    public void execute() {
        System.out.println(service.getResponse("Guice"));
    }
}

やっている事は単純にServiceに対して自分の名前を送っているだけです。

あとはClientクラスのオブジェクトを作成してServiceの実装をInjectして利用するだけですが、Guiceは設定ファイルを使いません。どうやってオブジェクトのインスタンスを作ったら良いのかを定義するためのクラスを作ります。

import com.google.inject.AbstractModule;

public class OkinawaModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Service.class).to(ServiceImpl.class);
    }
}

このconfigure()の中で、オブジェクト作成時に要求された抽象クラスに対して、実際に作成して注入する具象クラスの関係を記述していきます。
bind(Abstract).to(Concrete);と書く事で、InjectorはAbstract Classのインスタンスが必要になった時に Concrete Classのオブジェクトを作成して注入してくれます。
この例ではClientクラスを作成するときにServiceインターフェースのFieldに@Injectアノテーションがついていますので、Default Constructorでオブジェクト作成後、Fieldに対してServiceImplクラスのインスタンスが注入されます。

この抽象クラスと具象クラスをリンクさせることをLinked Bindingsと呼びます。

こうして書くとModuleクラスは設定ファイルみたいな物ですがCompilerが名前を検証してくれるのでXML等の設定ファイルと違ってCompile時にクラス名の誤りを検出できます。

Guiceでは依存関係を持たないそれぞれのComponentを、Moduleで組み立てるイメージのようで、あるConsumerに対して別の実装を組み合わせた形でオブジェクトを作りたい場合、設定ファイルを変更するようにModuleを変更するよりもModuleをもう一つ実装して、その中で別のconfigure()を定義してやるという感じで使う事を想定しているんだと思います。多分(^_^;)

最後にこれらのテストを実行するためのファイルを作成します。

import com.google.inject.Guice;
import com.google.inject.Injector;
public class Main {
    public static void main(String[] args) {
        // Injectorを作成する。この時にBindの設定を書いたModuleのInstanceを渡す。
        Injector injector = Guice.createInjector(new OkinawaModule());
        // クライアントのインスタンスを得る。
        // injectorがClientのServiceフィールドに依存関係を注入してくれます。
        Client client = injector.getInstance(Client.class);

        // 作成されたオブジェクトを使用します。
        client.execute();
    }
}

Injectorのインスタンスを先ほど作ったModuleを指定して作成します。
Injectorを作成するときにModuleは複数指定する事が出来ますので、複数のConsumerの作成方法はそれぞれ分離したファイルで管理する事が可能です。

Injectorが作成できたらgetInstance()を使って、インスタンスを作ってもらってそれを利用するだけです。

さて、実行してみましょう。コンパイルにも実行にも前回作ったdi.jarを使います。

>javac -cp di.jar;. *.java
>java -cp di.jar;. Main
ハイサイ!Guice

ってことで基本は確認できたので次回はScopeの制御をしてみよう。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.