CDIのProducesアノテーションを使ったインジェクション
【pom.xml】
CDIであれば他の設定は任意のもので大丈夫だと思います。
今回はDomaのクラスを使っていますが、他の何かしらのライブラリでも代用できます。
<dependencies> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>2.22.1</version> </dependency> <dependency> <groupId>org.seasar.doma</groupId> <artifactId>doma</artifactId> <version>2.5.0</version> </dependency> </dependencies>
【JAX-RSの設定】
今回のサンプルではJAX-RSを使って画面表示します。
(なぜなら結果を確認するのが簡単だから)
[Application]
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("/") public class ApplicationSetting extends Application { }
【ここから本題】
今回はDomaのDialectインターフェイスをインジェクションさせます。
Dialectはデータベースの方言を表すインターフェイスです。
設定 — Doma 2.0 ドキュメント
今回はbeans.xmlの設定によって切り替えるということをします。
デフォルトをPostgreSQL、OracleとMySQLはステレオタイプ指定というサンプルです。
[ステレオタイプ]
ステレオタイプは下記の二つです。
import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.enterprise.inject.Alternative; import javax.enterprise.inject.Stereotype; @Alternative @Inherited @Stereotype @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) public @interface UseOracle { }
import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.enterprise.inject.Alternative; import javax.enterprise.inject.Stereotype; @Alternative @Inherited @Stereotype @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) public @interface UseMySQL { }
【Producesアノテーション】
続いてステレオタイプによって切り替える部分です。
import javax.enterprise.context.Dependent; import javax.enterprise.inject.Default; import javax.enterprise.inject.Produces; import org.seasar.doma.jdbc.dialect.Dialect; import org.seasar.doma.jdbc.dialect.MysqlDialect; import org.seasar.doma.jdbc.dialect.OracleDialect; import org.seasar.doma.jdbc.dialect.PostgresDialect; @Dependent public class DialectProduces { @Produces @Default public Dialect getDefaultDialect() { return new PostgresDialect(); } @Produces @UseMySQL public Dialect getMySQLDialect() { return new MysqlDialect(); } @Produces @UseOracle public Dialect getOraDialect() { return new OracleDialect(); } }
全て戻り値の型はインジェクションしたいオブジェクトの型です。
javax.enterprise.inject.ProducesアノテーションをつけることによりCDIで管理されるようになります。
この書き方の場合はインジェクションされるたびに呼ばれます。
メソッドにスコープアノテーションをつけると挙動が変わります。
(この辺は気が向いたらエントリを書きます。たぶん・・・)
CDIの場合は型でインジェクションする対象が決まるようなので、
DefaultやステレオタイプをつけないとDIできないとデプロイ時にエラーになります。
【結果確認用ソース】
インジェクトされたオブジェクトのクラス名を返却します。
import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Response; import org.seasar.doma.jdbc.dialect.Dialect; @Path("dialect") @RequestScoped public class GetDialect { @Inject private Dialect dialect; @GET public Response view() { return Response.ok(dialect.getClass().getName()).build(); } }
【結果確認】
ブラウザから対象のリソースにアクセスするとPostgreDialectのフルネームが表示されます。
Defaultアノテーションがついたものです。
つづいて、クラスパスの配下に下記のようなMETA-INF/beans.xmlを置きます。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="annotated"> <alternatives> <stereotype>jp.glory.cdi.produces.UseMySQL</stereotype> <!-- パッケージは適宜変えてください --> </alternatives> </beans>
デプロイし直して再度アクセスすると今度はMysqlDialectのフルネームが表示されます。
ステレオタイプによって切り替えられているのがわかります。