これは、 CDIを環境で開始する方法と、 CDIを既存のJava EE 6アプリケーションに統合する方法について説明した後、CDIの依存性注入に関する2回目の投稿です( パート1 )。 この投稿では、CDIの実装のさまざまなポイント、 field 、 constructorおよびsetterについてお話したいと思います。 このため、前の例の一部を使用します: POJO ISBNジェネレーターをサーブレットに埋め込みます 。

フィールドインジェクション
前のすべての例で、クラスのフィールド(属性)に結び付けられた@Inject
アノテーションを見ました。
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { @Inject @ThirteenDigits private NumberGenerator numberGenerator; @Inject private ItemEJB itemEJB; ... }
提示されたコードでわかるように、 @ThirteenDigits
アノテーションと指定子(ここでは@ThirteenDigits
)が属性をマークしました。 しかし、他の多くの依存性注入フレームワークと同様に、CDIでは、コンストラクターまたはセッターを介して実装できます。
コンストラクター注入
属性の代わりに、コンストラクターに@Inject
注釈を追加できます。 特定の実装が必要な場合は、コンストラクターパラメーターを指定子でマークできます。
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { private NumberGenerator numberGenerator; private ItemEJB itemEJB; @Inject public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) { this.numberGenerator = numberGenerator; this.itemEJB = itemEJB; } ... }
ご覧のとおり、この場合、 @Inject
アノテーションはclass属性ではなく、コンストラクターを@Inject
た。 一方、 @ThirteenDigits
はコンストラクターをマークせず、そのnumberGenerator
パラメーター(論理的)をマークします。 必要に応じて、フィールドとコンストラクターを介して実装を混在させることができます(EJBのコンストラクターと属性を介して実装を使用する以下)。
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { private NumberGenerator numberGenerator; @Inject private ItemEJB itemEJB; @Inject public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator) { this.numberGenerator = numberGenerator; } ... }
ただし、ルールがあります : implementationを持つコンストラクタは1つしか持てません 。 コンテナはあなたではなく実装を行います(もちろん、管理された環境でコンストラクタを呼び出すことはできますが、期待どおりに機能しません)。 また、コンテナがすべての依存関係を正しく実装できるようにするBeanコンストラクタは1つだけです。 次のコードは正しくありません :
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { private NumberGenerator numberGenerator; private ItemEJB itemEJB; @Inject public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) { this.numberGenerator = numberGenerator; this.itemEJB = itemEJB; } @Inject public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator) { this.numberGenerator = numberGenerator; } ... }
ビンに複数のコンストラクターがある場合、ここに表示されます(もちろん、コードとエラーメッセージはWeld固有です)
WELD-000812 public @ WebServletクラスItemServletに使用するコンストラクターを決定できません。 可能なコンストラクタ[[constructor] @Inject public ItemServlet(NumberGenerator、ItemEJB)、[constructor] @Inject public ItemServlet(NumberGenerator)]
はい、フィールドとコンストラクターを同時に実装することは構文的に有効ですが、これには意味がありません。
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { @Inject @ThirteenDigits private NumberGenerator numberGenerator; @Inject private ItemEJB itemEJB; @Inject public ItemServlet(@ThirteenDigits NumberGenerator numberGenerator, ItemEJB itemEJB) { this.numberGenerator = numberGenerator; this.itemEJB = itemEJB; } ... }
セッター展開
別の方法があります-セッターを介して実装を使用する方法は、コンストラクターを介した実装のように見えます。 セッターを@Inject
アノテーションでマークし、その引数を修飾子でマークします。
@WebServlet(urlPatterns = "/itemServlet") public class ItemServlet extends HttpServlet { private NumberGenerator numberGenerator; private ItemEJB itemEJB; @Inject public void setNumberGenerator(@ThirteenDigits NumberGenerator numberGenerator) { this.numberGenerator = numberGenerator; } @Inject public void setItemEJB(ItemEJB itemEJB) { this.itemEJB = itemEJB; } ... }
コンストラクターまたはセッターを介して埋め込みを使用する場合、引数を指定する必要があります。 @Target(java.lang.annotation.ElementType.PARAMETER)
正しく宣言されていることを確認してください@Target(java.lang.annotation.ElementType.PARAMETER)
:
@Qualifier @Retention(RUNTIME) @Target({FIELD, TYPE, METHOD, PARAMETER}) public @interface ThirteenDigits { }
おわりに
1つの質問があるかもしれません(そして、私はPete Muirにも尋ねました):これまたはその実装ポイントをいつ使用する必要がありますか? しかし、この質問に対する技術的な答えはありません。個人的な好みの問題です。 管理された環境では、コンテナのみが展開を実行し、必要なのは正しい展開ポイントだけです。 ただし、コンストラクターまたはセッターを使用して実装する場合、必要に応じて、何らかの種類のロジックを追加できます(属性を使用して実装する場合は不可能です)。 しかし、すでに作成されたJava Beansとの後方互換性のために 、セッターによる実装が追加されたようです。
次の記事ではプロデューサーについて話します。
ソースコード
コードをダウンロードして、あなたがそれについてどう思うか教えてください。