2010年02月13日

CDIのBeanManagerを使ったBean取得と手動Inject

Weldかどうかに限らず動くはず〜。
基本的なBeanの取得(例外処理は省略)は、
BeanManager bm = InitialContext.doLookup("java:comp/BeanManager");

Bean<?> bean = bm.resolve(bm.getBeans(ClassA.class));
CreationalContext<?> cc = bm.createCreationalContext(bean);
ClassA result = (ClassA)bm.getReference(bean, ClassA.class, cc);

って感じかな〜。
この場合は最後にキャストね。

んで、インスタンスのフィールドのInjectとかを手動でしたいなら、
BeanManager bm = InitialContext.doLookup("java:comp/BeanManager");

@SuppressWarnings("unchecked")
Bean<ClassA> bean = (Bean<ClassA>)bm.resolve(bm.getBeans(ClassA.class));
CreationalContext<ClassA> cc = bm.createCreationalContext(bean);
AnnotatedType<ClassA> at = bm.createAnnotatedType(ClassA.class);
InjectionTarget<ClassA> it = bm.createInjectionTarget(at);
it.inject(targetOject, cc);

って感じかな〜。
この場合は、最初にキャストかな〜。

ClassAとか継承してるとresolveで一意にならないので気をつけないとね。
posted by そら at 12:41 | TrackBack(0) | 日記

Weld(CDI)のInjectの使い方、それは魔法

Weld(CDI)管理下にあれば、例えばフィールドに、
  @Inject
private ClassA hoge;
なんて書くだけでClassAが入る。

でも「ClassAの初期化に特別なことをしたい!」
ってこと、あるよね!え?ない?
……あることにしよう(強引)。
そんなときは、こんなのを用意してみる。

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, PARAMETER, FIELD})
public @interface Marker {
}
で、これを使って、
@Produces @Marker
public ClassA generateClassA() {
    // return ClassA Object;
    return new ClassA();
}
こんな風にすれば、@Marker(ClassA)の生成方法が指定できる。
対応したInject側は、こんな風に。
@Inject @Marker
private ClassA hoge;

つまり、好きなマーカー作って、それのProducesとInjectを作れば、
対応したマーカー間でInjectを自在にコントロールできるのだ!
……言い過ぎかな?(笑)

でもこれで、Userクラスをログインしたやつってことで@LoggedInとか
他にも@UserDatabaseとかが公式のサンプルにあるんだよね。
普通にInject出来ないやつとか、継承関係とかもこれでいけるかな?
他にも方法あるかもだけど。

乱用は良くないけど、適切に使えば可読性向上とか、依存関係の切り離しとか上手く調整できそうね〜。
posted by そら at 00:30 | TrackBack(0) | 日記