Android+Guice その4

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

前回説明したSingletonの初期化タイミングの制御について。Stageについての説明です。

今までInjectorを作るのにGuice.createInjector(new OkinawaModule());で作っていましたが更にStageを指定する事が可能です。

Guice.createInjector(Stage.DEVELOPMENT, new OkinawaModule());
または
Guice.createInjector(Stage.PRODUCTION, new OkinawaModule());

あとStage.TOOLというのもありますが、これはInjectionをしないモードなのでここでは扱いません。

DEVELOPMENTではStartup時間を早くするように動作し、PRODUCTIONではStartup時間は長くなるけどPerformanceが良くなる様に動作します。って事みたいです(^_^;)。

何はともあれ動作を見ましょう。以下のように書き換えてServiceImplが作成されたタイミングでメッセージを出力するようにします。

import com.google.inject.Singleton;

@Singleton
public class ServiceImpl implements Service {
    public ServiceImpl() {
        System.out.println("Created ServiceImpl instance.");
    }

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

StageをPRODUCTIONにします。

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;

public class Main {

    public static void main(String[] args) {
        System.out.println("Create Injector...");

        Injector injector = Guice.createInjector(Stage.PRODUCTION, new OkinawaModule());

        System.out.println("done.");

        Client client1 = injector.getInstance(Client.class);
        Client client2 = injector.getInstance(Client.class);

        // 実行する。
        client1.execute();
        client2.execute();

        // service の instanceはどうなった?
        if (client1.getService() == client2.getService()) {
            System.out.println("Service is singleton.");
        } else {
            System.out.println("Service is NOT singleton.");
        }
    }
}

これで実行してみます。Stage.PRODUCTIONです。

>javac -cp di.jar;. *.java
>java -cp di.jar;. Main
Created ServiceImpl instance.
Injector is created.
Create instance 1
Create instance 2
ハイサイ!Guice1
ハイサイ!Guice2
Service is singleton.

DEVELOPMENTステージに変更して実行します。

Injector is created.
Create instance 1
Created ServiceImpl instance.
Create instance 2
ハイサイ!Guice1
ハイサイ!Guice2
Service is singleton.

ServiceImplのインスタンスが作成されたタイミングが変わったのが分かるかと思います。GuiceではSingletonの初期化方法が二種類あってそれぞれタイミングが違うために起こります。

この二種類のSingleton(の初期化)はEager Singleton と Lazy Singletonと呼ばれています。
簡単に説明すると、要求されるまでオブジェクトを作らないLazyと要求される前に予め作っておくEagerという事です。
DEVELOPMENT Stageでは出来るだけLazyにして開始時間を短縮し(これによりCompile→Runという流れを速くします)、PRODUCTIONではEagerで作成しておいて利用される場面で高速に動作するように動きます。

Stage.DEVELOPMENTでも事前作成にしたいSingletonがある場合はbindする時に.asEagerSingleton()とする事で事前に作る事が可能です。

bind(Service.class).to(ServiceImpl.class).asEagerSingleton();

これでDEVELOPMENT StageでもInjectorが作成されたタイミングでSingletonが作成されます。

次回は再度Injectionの方法について。
…うーん、なかなかAndroid上で試すところまで到達しないな(笑)

Leave a Reply

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