GIN (GWT INjection)を使ってみる
GIN(GWT INjection)は、GoogleのDIフレームワークであるGuiceのGWT版で、GWTのクライアントサイドで使用するためのものです。現在リリースされているバージョンはGuice2.0ベースです。
モジュールの定義方法はGuiceと同じですが、GWTゆえの制約があります。GWTではクライアントコードではリフレクションは利用できないため、コンパイル時点での情報しか利用できません。そのためGuiceの一部の機能が使えなかったり、多少冗長なコードが必要になります。
GINを使う準備
GINのサイトからzipファイルをダウンロードして、
- gin-1.0.jar
- guice-2.0.jar
- aopalliance.jar
をビルドパスに追加します。
<inherits name="com.google.gwt.inject.Inject"/>
以上で準備は完了です。
GinModuleでモジュールを定義する
ここでは、Contactsアプリケーションで、Activityに必要なオブジェクト(View, RPCサービス, PlaceController)をインジェクトする例を使います。Activityには以下のようにコンストラクタインジェクションを行うために@Injectアノテーションを付加します。コンストラクタインジェクション以外に、メソッドインジェクション、フィールドインジェクションなども使用可能です。
public class ContactsActivity{ private ContactsView view; private PlaceController placeController; @Inject public ContactsActivity(ContactsServiceAsync rpcService, ContactsView view, PlaceController placeController) { this.rpcService = rpcService; this.view = view; this.placeController = placeController; } }
モジュールの定義は、GinModuleインタフェースを実装したクラスに記述します。以下の例ではAbstractGinModuleを継承して使用しています。
public class ContactsModule extends AbstractGinModule { @Override protected void configure() { bind(ContactsView.class).to(ContactsViewImpl.class).in(Singleton.class); bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class); bind(PlaceController.class).toProvider(PlaceControllerProvider.class).in(Singleton.class); } }
GINでオブジェクトを取得する
実際にオブジェクトがインジェクトされた状態のContactsActivityを取得するためには、以下のようにGinjectorを継承したクラスを用意して、
@GinModules(ContactsModule.class) public interface ContactsGinjector extends Ginjector{ ContactsActivity getContactsActivity(); }
GWT.createで生成したGinjectorを経由して取得します。
ContactsGinjector contactsGinjector = GWT.create(ContactsGinjector.class); ContactsActivity contactsGinjector.getContactsActivity();
Guiceであれば、以下のようなコードになると思いますが、GWTでは実行時にリフレクションが使用できないので、このようなコードになるようです。
Guice.getInjector().get(ConstantsActivity.class);
RPCサービスをインジェクトする
GINでは、RPCサービス(例のContactsServiceAsync)は、GWT.createを呼び出してインジェクトしてくれます。
また、インジェクトしたいクラスが見つからない場合にも、自動的にフォールバックしてGWT.create(対象クラス)が呼び出されます。
Providerを使用する
上記の例のPlaceControllerのように、デフォルトコンストラクタがなかったり@Injectを付けられないようなクラスのオブジェクトを提供するために、Providerを使用します。
public class PlaceControllerProvider implements Provider<PlaceController> { private EventBus eventBus; @Inject public PlaceControllerProvider(EventBus eventBus){ this.eventBus = eventBus; } @Override public PlaceController get() { return new PlaceController(eventBus); } }
この例のEventBusもGINによりインジェクトされます。