Doma 2.2.0からEntityListenerをDIコンテナから取得できるようになった
Doma 2.1.0まではEntityType
実装クラス(コンパイル時に自動生成されるクラス)のコンストラクタ内で単純にインスタンス化されていましたが、Doma 2.2.0からはConfig
にgetEntityListenerProvider
というメソッドが追加され、そのメソッドが返すEntityListenerProvider
をカスタマイズすることでEntityListener
のインスタンス取得をフックできるようになりました。
EntityListenerProvider
はEntityListener
のインスタンスを取得する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コンテナから取得できるようになると色々とインジェクションできるのも嬉しいですし、インターセプターをかますことも出来たりしてさらに嬉しいですね!!!
Discussion