web-dev-qa-db-ja.com

Java EEでCDIを使用する理由

Java EEでCDIを使用する方法を説明する記事がたくさんあることは知っていますが、これが実際にどのような利点をもたらすのか理解するのに苦労しています。たとえば、クラスがあるとします現在Fooのインスタンスを使用しています。

Foo myFoo = new Foo();

または

// Better, FooFactory might return a mock object for testing    
Foo myFoo = FooFactory.getFoo();

私は私ができるCDIでそれを読み続けます:

@Inject
Foo myFoo;

しかし、これは以前の工場ベースのアプローチよりも優れているのはなぜですか?私は知らない他のユースケースがあると思いますが、これを特定することができませんでした。

以下の応答を理解した場合、概念は、DIフレームワークが中央で構成されたマスターオブジェクトファクトリとして機能することです。これは合理的な解釈ですか?

更新

それ以来、Springの学習を開始しましたが、これは今ではずっと理にかなっています。以下のパラグラフは、Spring in Practiceから取ったもので、AccountServiceクラスの例を使用し、このクラスはAccountDao。長い引用をおaび申し上げますが、注入されたリソースが標準の初期化を超える何かを提供する理由の核心は本当に伝わると思います。

新しいキーワードを使用してAccountServiceを構築することもできますが、サービスレイヤーオブジェクトの作成はそれほど簡単ではありません。多くの場合、DAO、メール送信者、SOAPプロキシ、その他)に依存しています。これらの各依存関係をAccountServiceコンストラクターで(または静的初期化により)プログラムでインスタンス化できますが、スワップアウトされたときのカスケード変更

さらに、外部で依存関係を作成し、セッターメソッドまたはコンストラクター引数を介してAccountServiceに依存関係を設定できます。そうすることで、ハードな内部依存関係はなくなります(インターフェイスによってAccountServiceで宣言されている限り)が、初期化コードはどこにでも複製されます。 DAOを作成し、Springの方法でAccountServiceに接続する方法は次のとおりです。

<bean id="accountDao" class="com.springinpractice.ch01.dao.jdbc.JdbcAccountDao"/>

<bean id="accountService"
    class="com.springinpractice.ch01.service.AccountService">
    <property name="accountDao" ref="accountDao"/>
</bean>

上記のようにBeanを構成すると、プログラムはAccountServiceのインスタンスをSpring ApplicationContextから要求できるようになり、Spring DIフレームワークはインスタンス化が必要なものすべてをインスタンス化します。

49
PhilDin

CDIを作成した人々は、1つの大きなオブジェクトファクトリを提供しました。彼らはあなたよりもあなたのために仕事をしてくれました。 XML構成または注釈駆動型であるため、すべてをコードに埋め込む必要はありません。

Springのような依存性注入エンジンは、工場よりもはるかに多くのことを行います。それらが提供するすべてを複製するには、複数のファクトリクラスと1行のコードが必要です。

もちろん、使用する必要はありません。いつでも自由に独自のホイールを発明できます。そして、あなたはすべきです- あなたの目的がホイールの作り方を学ぶことである場合 または依存関係を排除します。

ただし、アプリケーションを開発するだけの場合は、他の人が提供するツールを使用するほうが有利です。

seminal article 依存性注入については、Martin Fowlerによって書かれました。読むことをお勧めします。 8年経った今でもすばらしい。

「それ以上のものはまだ明確ではない」

以下にいくつかの利点を示します。

  1. 緩いカップリング
  2. より簡単なテスト
  3. より良いレイヤリング
  4. インターフェイスベースの設計
  5. 動的プロキシ(AOPにセグエ)。
46
duffymo

依存性注入を使用する目的は、注入されたものを使用するコードがファクトリーに依存しないようにすることです。ファクトリコードの例には、コードに埋め込まれた静的メソッド呼び出しがありますが、DIアプローチでは必要ありません。

myFooでインジェクトされているものは、ファクトリーについて知る必要はありません。

17
Nathan Hughes

これは、エンタープライズプログラミングとは何かに関する重要かつ微妙な質問です。

名前は適切に選択されています:コンテキストと依存関係。

CDIは、優れたコードやクリーンなコードとは関係ありません。大規模な組織が複雑な分散ソフトウェアシステムを構築し、データを共有できるようにすることです。それは、政府や他の官僚が、管理するソフトウェアの各部分について、自己完結した、十分に文書化されたパッケージを無差別に配布できることを100%確実にすることです。最近では、ほぼすべてのPOJOを注入できることに注意してください。

ある種のクライアントアプリを作成していて、隅にユーザーの名を印刷したいとします。

  • この大企業のエンタープライズアーキテクトはこの機能を使用したいと考えていますが、ジュニアソフトウェアエンジニアとして、DBにキーを渡す機会はありません。

  • また、ネットワーク全体でデータを保護したいと考えていますが、データのスクラップを共有する必要があるたびに認証クライアントをリエンジニアリングするためのエンジニアへの支払いは行っていません。

  • 彼らはあなたにこの情報を問い合わせて更新できるようにしたいのですが、トランザクションはどのアプリよりも高いレベルで処理されることを望んでいます。

  • 彼らはあなたがセットアップブロックで些細なモックであなたのクラスをテストできることを望んでいます。

  • クラス間のカップリングには、最小限の静的メソッドが必要です。

  • そしてどんどん...

ほとんどのJSRには、おそらく「EAができることを望んでいます...」がどこかに埋め込まれています。

CDIは、大規模な(任意?)水平および垂直スケールのアプリがコンテキスト、依存関係、したがってデータを共有できるため、推奨されます

ファウラーの言葉で:

「問題は、リスタークラスが実装クラスを知らないようにリンクを作成する方法ですが、それでもインスタンスと通信して作業を行うことができます。」

「しかし、このシステムをさまざまな方法で展開したい場合は、プラグインを使用してこれらのサービスとのやり取りを処理する必要があるため、さまざまな展開でさまざまな実装を使用できます。」

「これらのコンテナが使用するアプローチは、プラグインのすべてのユーザーが、個別のアセンブラモジュールがリスタに実装を注入できるようにする何らかの規則に従うようにすることです。」

簡単に言えば、複雑なエンタープライズアプリケーションの集中化された「コマンドアンドコントロール」を可能にします。 Java EEは体系化された、信頼できる抽象化プロセスであり、CDIはそれがうまく機能し、ほとんど目に見えないようにするものです。複雑なアプリをつなぎ合わせるのはほとんど簡単です。

さらに2つのこと:

  1. CDIは、Java EEのJNDIとして知られる「サービスロケーターパターン」と一緒に平和的に存在することに注意してください。

  2. CDIは、多くの場合、特に非エンタープライズ(文字通り)の場合に必要とされるよりも強力です。

5
jordanpg

高レベルでは、CompSciのほとんどのものと同様に、間接的レベル(または抽象化)を提供します。アプリケーションでFoo myFoo = new Foo();としてハードコーディングされます。その間接化は、疎結合コードをもたらし、それにより物事をモジュール化し、より簡単な方法でクラスやサブシステムの交換、サービス、テストを容易にします。

インダイレクション/抽象化には多くのデザインとパターンがあることに注意してください-依存性注入はただ1つです。

質問のもう1つの側面は、「なぜCDIなのか」です。 -まあ、誰かがすでにあなたのために仕事をしているからです。 always独自のものを構築できますが、予算の下で実行する必要のある現実のシステムを構築することが目的である場合、通常は時間の無駄です時間。ミシュランの星付きシェフがあなたのために喜んでその仕事をしてくれるのに、なぜ食料品や料理に悩むのですか?

4
DeepSpace101