BeanManagerでCDIコンテナにアクセスする
2011/11/03 コメントを残す
CDI拡張モジュールを作る上でコンテナが管理する情報を取得・操作できたら便利です。今回はそれを可能にするBeanManagerについて紹介します。これは、今までCDI拡張モジュールのインタフェースでたびたび登場していたけど、説明をさぼっていたものです。
BeanManagerとは
BeanManagerは拡張モジュールからコンテナにアクセスするときに使うもので、これを使うことでBean、インターセプタ、デコレータを取得することができます。
BeanManagerを取得するには、Beanのクラス内において
@Inject BeanManager manager;
のようにインジェクションするだけです。
BeanManagerは次のような機能を提供します。
メタデータ関連
- AnnotatedTypeを生成する
- InjectionTargetを生成する
イベント関連
- イベントを発行する
Bean関連
- Beanを取得する
- Beanリファレンスを取得する
- CreationalContextを生成する
- コンテキストを取得する
アノテーション関連
- アノテーション定義を取得する
- インターセプタバインディング定義
- ステレオタイプ定義
- 各種アノテーションの判別(限定子か否か、NormalScopeか否か, etc.)
依存性解決関連
- Beanを特定する
- デコレータを特定する
- インターセプタを特定する
- デコレータを特定する
メソッドの概要を表1にまとめます。正確な定義はJavaDocを参照してください。
戻り値 | メソッド | 概要 |
---|---|---|
AnnotatedType<T> | createAnnotatedType(Class<T> type) | 指定されたクラスまたはインタフェースのアノテーションを読むために利用できるAnnotatedTypeを取得する |
CreationalContext<T> | createCreationalContext(Contextual<T> contextual) | 指定されたcontextualタイプまたは非contextualオブジェクトのためにcreationalContextを取得する |
InjectionTarget<T> | createInjectionTarget(AnnotatedType<T> type) | 指定されたAnnotatedTypeのためのInjectionTargetを取得する |
void | fireEvent(Object event, Annotation… qualifiers) | イベントを発火し、オブザーバに通知する |
Set<Bean<?>> | getBeans(String name) | EL名レゾリューション規則に従って、指定されたEL名に対応するBeanのセットを返す |
Set<Bean<?>> | getBeans(Type beanType, Annotation… qualifiers) | タイプセーフ・レゾリューション規則に従って、指定されたタイプと限定子に対応するBeanのセットを返す |
Context | getContext(Class<? extends Annotation> scopeType) | 指定されたスコープタイプのアクティブなコンテキストを取得する |
javax.el.ELResolver | getELResolver() | EL名によってBeanを特定するELResolverを返す |
Object | getInjectableReference(InjectionPoint ij, CreationalContext<?> ctx) | 指定されたインジェクションポイントのためにインジェクション可能なリファレンスを取得する |
Set<Annotation> | getInterceptorBindingDefinition(Class<? extends Annotation> bindingType) | 指定されたインターセプタバインディングタイプのためのメタアノテーションのセットを取得する |
Bean<?> | getPassivationCapableBean(String id) | 指定されたIDを持つPassivationCapableBeanを返す |
Object | getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx) | 指定されたBeanとBeanタイプのためのコンテキスト参照を取得する |
Set<Annotation> | getStereotypeDefinition(Class<? extends Annotation> stereotype) | 指定されたステレオタイプのメタアノテーションを取得する |
boolean | isInterceptorBinding(Class<? extends Annotation> annotationType) | 指定されたアノテーションがインターセプタバインディングか否か |
boolean | isNormalScope(Class<? extends Annotation> annotationType) | 指定されたアノテーションがNormalScopeか否か |
boolean | isPassivatingScope(Class<? extends Annotation> annotationType) | 指定されたアノテーションがPassivatingScopeか否か |
boolean | isQualifier(Class<? extends Annotation> annotationType) | 指定されたアノテーションが限定子か否か |
boolean | isScope(Class<? extends Annotation> annotationType) | 指定されたアノテーションがScopeか否か |
boolean | isStereotype(Class<? extends Annotation> annotationType) | 指定されたアノテーションがステレオタイプか否か |
Bean<? extends X> | resolve(Set<Bean<? extends X>> beans) | 曖昧な依存性解決規則を指定されたBeanのセットに対して適用する |
List<Decorator<?>> | resolveDecorators(Set<Type> types, Annotation… qualifiers) | タイプのセットと限定子のセットのためのデコレータのリストを返す |
List<Interceptor<?>> | resolveInterceptors(InterceptionType type, Annotation… interceptorBindings) | インターセプタバインディングとインターセプションのタイプのためのインターセプタのリストを返す |
Set<ObserverMethod<?super T> | resolveObserverMethods(T event, Annotation… qualifiers) | イベントのためのオブザーバのリストを返す |
void | validate(InjectionPoint injectionPoint) | 指定されたインジェクションポイントの妥当性を検証する |
javax.el.ExpressionFactory | wrapExpressionFactory(javax.el.ExpressionFactory expressionFactory) | 指定されたExpressionFactoryのラッパーを返す。それはMethodExpressionとValueExpressionの生成をExpressionFactoryに移譲する。 |
コンテナが管理するBeanの取得
BeanManagerを使ってデプロイされたBeanにアクセスしてみましょう。以下のコードではすべてのBeanを集めてプリントします。
@Inject private BeanManager beanManager; // ... Set<Bean<?>> beans = beanManager.getBeans(Object.class, new AnnotationLiteral<Any>(){}); for (Bean<?> bean: beans) { System.out.println("bean=" + bean.getBeanClass().getSimpleName() + ", scope=" + bean.getScope().getSimpleName()); }
これをWeldのexamples/jsf/login内で実行した結果は次の通り。このブログの過去の記事で作成したMyBeanやMyApplicationContext、それからContextRegistrationのような拡張モジュールまでWeld実装内部ではBeanとして管理されていることがわかります。
22:50:39,042 INFO [stdout] (http--127.0.0.1-8080-1) bean=InjectionPoint,scope=Dependent 22:50:39,043 INFO [stdout] (http--127.0.0.1-8080-1) bean=MyBean2,scope=Dependent 22:50:39,043 INFO [stdout] (http--127.0.0.1-8080-1) bean=Validator,scope=Dependent 22:50:39,043 INFO [stdout] (http--127.0.0.1-8080-1) bean=ValidatorFactory,scope=Dependent 22:50:39,044 INFO [stdout] (http--127.0.0.1-8080-1) bean=MyApplicationContext,scope=Dependent 22:50:39,044 INFO [stdout] (http--127.0.0.1-8080-1) bean=MyBean,scope=MyApplicationScoped 22:50:39,044 INFO [stdout] (http--127.0.0.1-8080-1) bean=ContextRegistration,scope=ApplicationScoped 22:50:39,045 INFO [stdout] (http--127.0.0.1-8080-1) bean=ManagedBeanUserManager,scope=RequestScoped 22:50:39,045 INFO [stdout] (http--127.0.0.1-8080-1) bean=InstanceImpl,scope=Dependent 22:50:39,046 INFO [stdout] (http--127.0.0.1-8080-1) bean=Resources,scope=Dependent 22:50:39,046 INFO [stdout] (http--127.0.0.1-8080-1) bean=Conversation,scope=RequestScoped 22:50:39,046 INFO [stdout] (http--127.0.0.1-8080-1) bean=Principal,scope=Dependent 22:50:39,047 INFO [stdout] (http--127.0.0.1-8080-1) bean=EventImpl,scope=Dependent 22:50:39,047 INFO [stdout] (http--127.0.0.1-8080-1) bean=UserTransaction,scope=Dependent 22:50:39,048 INFO [stdout] (http--127.0.0.1-8080-1) bean=ManagedBeanUserManager,scope=RequestScoped 22:50:39,048 INFO [stdout] (http--127.0.0.1-8080-1) bean=Login,scope=Dependent 22:50:39,049 INFO [stdout] (http--127.0.0.1-8080-1) bean=BeanManagerImpl,scope=Dependent 22:50:39,049 INFO [stdout] (http--127.0.0.1-8080-1) bean=Resources,scope=Dependent 22:50:39,049 INFO [stdout] (http--127.0.0.1-8080-1) bean=User,scope=Dependent 22:50:39,050 INFO [stdout] (http--127.0.0.1-8080-1) bean=Login,scope=SessionScoped 22:50:39,050 INFO [stdout] (http--127.0.0.1-8080-1) bean=Resources,scope=Dependent 22:50:39,050 INFO [stdout] (http--127.0.0.1-8080-1) bean=Credentials,scope=RequestScoped