Guiceとの連携案

Guiceを使った場合に、DomaのConfigクラスのインスタンスをDaoImplにどうインジェクトするのがベターか?という話です。
昨日のConfigAdapterDomaが提供するという前提で話をすすめたいと思います。

案1 明示的なコンストラクタインジェクション

Daoの設定はこんな感じで普通。

@Dao(config = ConfigAdapter.class)
public interface EmpDao {
    ...
}

aptで生成される実装クラスも普通。

public class EmpDaoImpl extends ... implements EmpDao {

     public EmpDaoImpl(Config config) {
          super(new ConfigAdapter(config));
     }
     ...
}

Moduleでは、DaoImplを自分でnewしてtoInstance()してインタフェースと関連付けます。そのとき明示的にconfigをコンストラクタに渡します。

public class DomaModule extends AbstractModule {

    @Override
    protected void configure() {
        Config config = buildConfig();
        bind(EmpDao.class).toInstance(new EmpDaoImpl(config));  // DaoImplを自分でnew。そのときconfigを明示的にインジェクト。
        bind(DeptDao.class).toInstance(new DeptDaoImpl(config));
    }

    protected Config buildConfig() {
         ...
    }

}

ということで、この案ではDomaは特に新しいことは何もしません。

案2 アノテーションによるコンストラクタインジェクション

これは、Domaがaptで生成するDaoImplのソースコードにインジェクション用のアノテーションをつけてしまおうというものです。こんな感じで考えました。Daoに@AnnotateWithを使ってどこに何のアノテーションをつけるのかを指定します。

@Dao(config = ConfigAdapter.class)
@AnnotateWith(annotations = {
        @Annotation(target = AnnotationTarget.CONSTRUCTOR, type = Inject.class),
        @Annotation(target = AnnotationTarget.CONSTRUCTOR_PARAMETER, type = Named.class, elements = "hoge") })
public interface EmpDao {

    ...
}

Daoの実装クラスは@Injectと@Namedが付与されてこうなります。

public class EmpDaoImpl extends ... implements EmpDao {

     @Inject
     public EmpDaoImpl(@Named("hoge") Config config) {
          super(new ConfigAdapter(config));
     }

     ...
}

Moduleでは、to()してインタフェースと実装クラスを関連付けます。ConfigのインジェクションはGuiceにおまかせ。

public class DomaModule extends AbstractModule {

    @Override
    protected void configure() {
        Config config = buildConfig();
        bind(Config.class).annotatedWith(Names.named("hoge")).toInstance(config);
        bind(EmpDao.class).to(EmpDaoImpl.class); // 案1とちがい、ここは to
        bind(DeptDao.class).to(EmpDaoImpl.class);
    }

    protected Config buildConfig() {
         ...
    }

}

この案では、Domaは実装クラスにアノテーションをつけるようなコードを出力するようにがんばります。



案1でもいいかなーとは思うのですが、なんかデメリットがあるのかも。AOPが使えないとかします?
案2は、GuiceだけではなくSpringやSeasar2にも有効です。アノテーションはクラス、コンストラクタ、コンストラクタのパラメータの3つの場所に好きな数だけつけられて、DIに関係ないアノテーションもOKです。こっちの案を採用しても案1の方法も使えます。

どっちがいいとかこうしたほうがいいとか意見があったらおねがいします、id:shot6さん、id:c9katayamaさん、id:yone098さん。