⛄️

Doma 2.2.0からEntityListenerをDIコンテナから取得できるようになった

2015/03/28に公開

Doma 2.1.0まではEntityType実装クラス(コンパイル時に自動生成されるクラス)のコンストラクタ内で単純にインスタンス化されていましたが、Doma 2.2.0からはConfiggetEntityListenerProviderというメソッドが追加され、そのメソッドが返すEntityListenerProviderをカスタマイズすることでEntityListenerのインスタンス取得をフックできるようになりました。

EntityListenerProviderEntityListenerのインスタンスを取得するgetメソッドを持っています。
EntityListenerProvider.getメソッドのデフォルト実装は次のようになっています。

default <ENTITY, LISTENER extends EntityListener<ENTITY>> LISTENER get(
        Class<LISTENER> listenerClass, Supplier<LISTENER> listenerSupplier) {
    return listenerSupplier.get();
}

ご覧のように単純にSupplier.getメソッドを実行しているだけです。

このEntityListenerProvider.getメソッドをオーバーライドしてDIコンテナからEntityListenerのインスタンスを取得する例を書きます。
この例ではGuiceを使用しておりConfig実装クラスとEntityListenerProvider実装クラスもGuiceで管理しています。

まずはEntityListenerProvider実装クラス。
GuiceのInjectorをインジェクションしてそこからEntityListenerのインスタンスを取得しています。

package sample;

import java.util.function.Supplier;

import javax.inject.Inject;

import org.seasar.doma.jdbc.EntityListenerProvider;
import org.seasar.doma.jdbc.entity.EntityListener;

import com.google.inject.Injector;

public class SampleEntityListenerProvider implements EntityListenerProvider {

    @Inject
    private Injector injector;

    @Override
    public <ENTITY, LISTENER extends EntityListener<ENTITY>> LISTENER get(
            Class<LISTENER> listenerClass, Supplier<LISTENER> listenerSupplier) {
        return injector.getInstance(listenerClass);
    }
}

次にConfig実装クラス。
EntityListenerProviderをインジェクションしてそのまま返しているだけです。

package sample;

import javax.inject.Inject;
import javax.sql.DataSource;

import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.EntityListenerProvider;
import org.seasar.doma.jdbc.dialect.Dialect;

public class SampleConfig implements Config {

    @Inject
    private EntityListenerProvider entityListenerProvider;

    @Inject
    private DataSource dataSource;

    @Inject
    private Dialect dialect;

    @Override
    public EntityListenerProvider getEntityListenerProvider() {
        return entityListenerProvider;
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }
}

Guice以外のDIコンテナでも似たような方法を取れるでしょう。 例えばCDIだとInjectorではなくBeanManagerをインジェクションしてBeanManagerからEntityListener実装クラスのインスタンスをルックアップすると良いと思います。(CDI
1.1以降であればCDI.current().select(listenerClass)でも良いと思います)

EntityListenerをDIコンテナから取得できるようになると色々とインジェクションできるのも嬉しいですし、インターセプターをかますことも出来たりしてさらに嬉しいですね!!!

https://github.com/backpaper0/doma-listener-from-dicontainer-sample

Discussion