アノテーションを指定したBeanの検索方法

前回のブログでBeanManagerを紹介しましたが、AnnotationLiteralの使い方の説明が足りなかったと思いますので補足します。

AnnotationLiteralを使うとアノテーションを「もの」として扱える

BeanManagerの使用例として取り上げたBeanManager:: getBeans(Type beanType, Annotation… qualifiers) はメソッド引数として限定子(Qualifier)アノテーションを要求しています。しかし、使用例ではこのメソッド引数としてAnnotationLiteralのインスタンスが指定されていました。

Set<Bean<?>> beans = beanManager.getBeans(Object.class, new AnnotationLiteral<Any>(){});

AnnotationはもともとインタフェースというのがJavaでの定義なので、それをメソッド引数として渡すためにはAnnotationインタフェースを実装した何らかのクラスが必要になります。クラスAnnotationLiteral<T extends Annotation>はCDIによって導入されたものでAnnotationインタフェースの実装をワンライナー(1行プログラム)として書けるようにしたものです。上の例では、アノテーションAnyを引数として渡すためにAnnotationLiteral<Any>のインスタンスを作成しています。

このように、APIを使って実行時にAnnotationを指定するというシーンでAnnotationLiteralが使われます。JavaのアノテーションはそもそもはJavaコード上に@Anyのようにしてメタデータを付加するのに使われるものです。しかし、今回のようにAPIを使ってアノテーションを指定して検索をするような場合にはアノテーションを「もの」として扱える方が便利です。

Instanceを使うとコンテキストからインスタンスを取得できる

AnnotationLiteralを使った別の例を紹介します。CDIにはAPIを使ってコンテキストにバインドしたインスタンスを取得するIntanceというクラスが提供されています。これはCDI拡張モジュール開発者のための機能というよりは、むしろアプリケーション開発向けに提供されている一般的な機能です(詳しくはWeld参照文書を見てください)。

@Inject Instance<PaymentProcessor> paymentProcessorSource;

実際にインスタンスを取得するにはInstanceに対してget()を実行します。get()を実行することで、CDIコンテナは指定されたクラスPaymentProcessorのBeanインスタンスを特定し、その結果を返します。つまり、アプリケーションがインジェクションのタイミングをget()によって制御できるようになります。

PaymentProcessor p = paymentProcessorSource.get();

しかし、コンテキスト上にPaymentProcessortという型の複数のBeanの候補が存在した場合(例えばPaymentProcessorのサブクラスのBeanが複数存在した場合)はCDIコンテナはBeanを1つに特定することができず、結果として例外がスローされます。そこで、次の例のように@Asynchronousという限定子を指定することでユニークがBeanが特定されるようにします。

@Inject @Asynchronous Instance<PaymentProcessor> paymentProcessorSource;

こうすることで例外は避けられるようになりましたが、このようにInstanceの宣言時に限定子を追加していくやり方では、(実行時にContexualなインスタンスを取得するという)Instanceを使う甲斐がありません。Instanceには実行時に検索条件として限定子を指定するselect() というメソッドが提供されていますので、そこでAnnotatlinLiteralを使います。

PaymentProcessor p = paymentProcessorSource
 .select(new AnnotationLiteral<Asynchronous>() {});

BeanManagerとInstanceの例からCDIでBeanの検索をするときにAnnotationLiteralが便利に使えることがわかりました。次回は、CDI拡張モジュールの作り方の話に戻って、AnnotationLiteralを使ってAnnotationの挙動を変更する方法について書くつもりです。

広告

現在コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。