web-dev-qa-db-ja.com

メソッドパラメータインジェクションにCDIを使用する方法

CDIを使用してパラメーターをメソッド呼び出しに挿入することは可能ですか?予想される動作はフィールド注入と同様です。優先生産者が検索され、製品が使用されます。

私がしたいのはこれです:

public void foo(@Inject Bar bar){
  //do stuff
} 

またはこれ(混乱の少ない構文):

public void foo(){
  @Inject 
  Bar bar;
  //do stuff
} 

この構文はどちらの場合も不正です。代わりはありますか?いいえの場合-可能であれば、何らかの理由でこれは悪い考えでしょうか?

ありがとうございました

[〜#〜] edit [〜#〜]-要件を十分に明確にしていない可能性があります-bar変数をコンテナに。ヨルン・ホルストマンとパーセプションの答えは、それが不可能であることを示唆しています。

20
kostja

インジェクションポイントは、コンテナによってインスタンス化されるときにBeanに対して処理されます。これにより、メソッドレベルのインジェクションのユースケースの数が制限されます。現在のバージョンの仕様では、次のタイプのメソッドインジェクションが認識されます。

初期化メソッドの注入

public class MyBean {
    private Processor processor;

    @Inject
    public void setProcessor(final Processor processor) {
        this.processor = processor;
    }
}

MyBeanのインスタンスが挿入されると、そのセッターメソッドを介してプロセッサインスタンスも挿入されます。

イベントオブザーバーメソッド

public class MyEventHandler {
    public void processSomeEvent(@Observes final SomeEvent event) {
    }
}

イベントインスタンスは、イベント処理メソッドに直接注入されます(ただし、@ Injectアノテーションは使用されません)。

プロデューサーメソッド

public class ProcessorFactory {
    @Produces public Processor getProcessor(@Inject final Gateway gateway) {
        // ...
    }
}

プロデューサーメソッドへのパラメーターは自動的に挿入されます。

19
Perception

あなたが本当に望んでいるのは、メソッドのパラメーター(呼び出し元によって提供される必要があります)としてではなく、メソッドが呼び出され、完全に構築されて注入されるたびに適切に初期化されたCDI Beanのインスタンスである場合は、次を確認します。

javax.inject.Provider<T>

基本的に、最初にクラスにプロバイダーを注入します

@Inject Provider<YourBean> yourBeanProvider;

次に、メソッドで新しいインスタンスを取得します

YourBean bean = yourBeanProvider.get();

お役に立てれば :)

9
Bing Ren

この質問は、私がこのトピックを最初に検索したときに出てきました。それ以来、CDI 1.1のリリース(JavaEE 7仕様に含まれています)によって、OPが望むものを実際に部分的に実行する方法があることがわかりました。あなたはまだできません

_public void foo(@Inject Bar bar){
   //do stuff
}
_

ただし、_@Inject_を使用せず、プログラムで次のように注入されたインスタンスを検索する場合でも、ローカル変数を「注入」できます。

_public void foo() {
    Instance<Bar> instance = CDI.current().select(Bar.class);
    Bar bar = instance.get();
    CDI.current().destroy(instance);
    // do stuff with bar here
}
_

select()メソッドは、必要に応じて、提供する必要のある修飾子アノテーションをオプションで取ることに注意してください。 _Java.lang.annotation.Annotation_のインスタンスを取得して頑張ってください。 _Instance<Bar>_を繰り返し処理して、必要なものを見つける方が簡単な場合があります。

上記のように_Instance<Bar>_を破棄する必要があると言われました。経験から、上記のコードが機能することを確認できます。しかし、私はあなたがそれを破壊することを誓うことはできません必要

8
dcsohl

CDIのその機能は、「初期化メソッド」と呼ばれます。構文はコードとは異なり、メソッド全体に@Injectの注釈が付けられます。さらに、修飾子によってメソッドパラメータに注釈を付けて、特定のBeanを選択できます。 JSR 299 のセクション3.9は、次の例を示しています。@Selectedは、Bean実装が1つしかない場合は省略できる修飾子です。

@Inject
void setProduct(@Selected Product product) {
    this.product = product;
}

その点に注意してください

アプリケーションは初期化メソッドを直接呼び出すことができますが、コンテナからメソッドにパラメータが渡されることはありません。

5
Jörn Horstmann

メソッドでBeanManager APIを使用してコンテキスト参照を取得できます。または、最終的な目標に応じて、

Instance<Bar>

メソッドの外でメソッドで使用します。

1
covener