CDIでの依存性注入。 パート2

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







COFFEE_BEANS







フィールドインジェクション



前のすべての例で、クラスのフィールド(属性)に結び付けられた@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との後方互換性のために 、セッターによる実装が追加されたようです。







次の記事ではプロデューサーについて話します。







ソースコード



コードダウンロードして、あなたがそれについてどう思うか教えてください。








All Articles