2016-10-06 7 views
30

Spring MVCPortletsについては、いくつかの投稿でフィールド注入をお勧めしません。私は私がフィールド注入を使用していると私はそれに答えることができないので、私は自分自身を求めているので、私は取得しようとしています。私はそれを理解として、あなたはこのような@Autowiredを持つ属性へBeanを注入した場合フィールド注入は次のとおりです。フィールドインジェクションとは何か、それを避ける方法は?

CartController.java:

... 
@Autowired 
private Cart cart; 
... 

BookshopConfiguartion.java:

@Configuration 
public class BookShopConfiguration { 

@Bean 
public Cart cart(){ 
    return new Cart(); 
} 
//more configuration 

私のCart.javaは、カート内の本。私の研究の間に

私はおよそコンストラクタ・インジェクションをお読みください。

MyComponent.java:

... 
public class MyComponent{ 
private Cart cart; 

@Autowired 
public MyComponent(Cart cart){ 
    this.cart = cart; 
} 
... 

利点と注射のこれらのタイプの両方の欠点は何ですか?


EDIT 1:この質問は、私はそれをチェックしthis questionの重複としてマークされています。私が正しいと思っているのであれば、質問にも答えにも、私には分からないコード例はありません。

答えて

70

インジェクションタイプ

依存性は、Beanに注入することができる方法の3つのオプションがありますセッターまたは他の方法によって コンストラクタを通して1 2. 3.直接フィールド

に反射によってオプション3を使用しています - つまり、自分のフィールドで@Autowiredを直接使用する場合です。


インジェクションガイドライン

一般的なガイドライン、as recommended also by Springは(コンストラクタベースまたはセッターベースDIの項を参照)、以下の通りである必須の依存関係について

  • または不変性を目指して、コンストラクタインジェクションを使用する
  • オプションまたは変更可能な依存関係については、セッタインジェクションを使用する
  • ほとんどの場合、フィールド注入を避けてください。

フィールド注入欠点

フィールド噴射が眉をひそめている理由は次のとおりです。

  • あなたのクラスが持つコンストラクタ・インジェクション
  • と同じようにあなたは不変オブジェクトを作成することはできませんDI容器と密閉結合して使用することはできません
  • クラスをインスタンス化することはできません(ユニットテストなど)。
  • 実際の依存関係は外部から隠されていて、インターフェイス(コンストラクタまたはメソッド)に反映されません。
  • 10の依存関係を持つのは本当に簡単です。コンストラクタインジェクションを使用していた場合、コンストラクタに10個の引数を指定すると、何かが怪しいことが通知されます。しかし、フィールド注入を無期限に使用して注入フィールドを追加できます。依存性があまりにも多いと、クラスが通常複数のことを行い、それが単一責任原則に違反する可能性がある赤い旗です。

結論

ニーズに応じて、主にコンストラクタ・インジェクションまたはコンストラクタとセッター注入のいくつかの組み合わせを使用する必要があります。フィールド注入には多くの欠点があり、避けるべきです。フィールド注入の唯一の利点は、すべての短所を上回らない書込みがより便利であることです。さらに

を読む


私は、フィールド注入は通常推奨されない理由についてのブログ記事を書いた - あなたはここでそれを確認することができます - Field Dependency Injection Considered Harmfulを。

+4

世界に伝えるのは良い考えではなく一般的ではありません。 "フィールド注入は避けるべきです"。賛否両論を表示し、自分に決断を下す;)多くの人々は、他の経験や物事を見る方法を持っています。 – dit

+4

ここにあるかもしれませんが、コミュニティが何かを落胆させるための一般的なコンセンサスになった他のケースがあります。たとえば、ハンガリー表記を考えてみましょう。 – Jannik

+0

あなたはテスト容易性と依存性の可視性としていくつかの良い点を挙げていますが、私はすべてに同意していません。コンストラクタインジェクションに欠点はありませんか?コールの実際の構成を実行するクラスに注入するために5つまたは6つのフィールドを有することが望ましいことがある。私は不変性を持ってあなたにも同意しない。最終フィールドを持つことは、クラスを不変にすることを強制するものではありません。それが望ましい。これは非常に異なっています。 – davidxxx

11

味の問題。あなたの決断です。

しかし、私はなぜコンストラクタの注射を使わないのか説明することができます。

  1. 私はすべての@Service@Repository@Controller豆のコンストラクタを実装する必要はありません。つまり、約40〜50豆以上があります。新しいフィールドを追加するたびに、コンストラクタを拡張する必要があります。いいえ、私はそれが欲しいと私はする必要はありません。

  2. あなたのBean(サービスまたはコントローラ)が多くの他のBeanを注入する必要がある場合はどうなりますか? 8つのパラメータを持つコンストラクタは非常に醜いです。

  3. 私がCDIを使用している場合、コンストラクタは私には関係ありません。


EDIT: Vojtech Ruzickaは言った:

クラスは、あまりにも多くの依存関係を持っているし、おそらく単一 責任の原則に違反しているとはい

をリファクタリングする必要があります。理論と現実。 例:DashboardControllerが単一パス*:8080/dashboardにマップされています。

私のDashboardControllerは、他のサービスから大量の情報を収集し、ダッシュボード/システム概要ページに表示します。私はこの単一のコントローラが必要です。ですから、この1つのパス(基本認証またはユーザーロールフィルター)のみを保護する必要があります。

+10

8つの依存関係を持つ非常に醜いコンストラクタは、何かが間違っているという赤い旗であり、クラスが多すぎる依存関係を持ち、おそらくは単一責任の原則に違反しているため、リファクタリングする必要があります。それは実際には良いことです。 –

+1

@VojtechRuzickaそれは良いことではありませんが、時にはそれを避けることはできません。 – dit

+2

私は3の経験則、40-50はもちろん、どのクラスの依存関係も、あなたがリファクタリングする必要があるサインであると言いたいと思います。 40の依存関係を持つクラスが、単一の責任プリンシパルまたはオープン/クローズプリンシパルに固執する方法はありません。 –

17

これはソフトウェア開発における終わりのない議論の1つですが、業界の主要な影響力者はそのトピックについてより多くの意見を求めており、より良い選択肢としてコンストラクタインジェクションを提案し始めました。

コンストラクタ・インジェクション

長所:

  • より良いテスト容易性。単体テストでは、疑似ライブラリやSpringコンテキストは必要ありません。 新しいキーワードを使用してテストするオブジェクトを作成できます。このようなテストは、反射メカニズムに依存しないため、常に高速です。 (This questionは30分後に尋ねられました。作者がコンストラクタインジェクションを使用していたなら、それは現れませんでした)。
  • 不変性。依存関係が設定されると、変更することはできません。
  • 安全コード。コンストラクタの実行後、パラメータとして渡されたものを検証できるように、オブジェクトはすぐに使用できます。オブジェクトは準備ができていてもいなくてもよく、中間に状態はありません。フィールドインジェクションでは、オブジェクトが壊れやすい中間ステップを導入します。
  • 必須依存関係のクリーナー表現。この問題では、フィールド注入があいまいです。
  • 開発者はデザインを考えるようになります。 ditは8つのパラメータを持つコンストラクタについて書きました。これは実際には悪いデザインの兆候であり、the God object anti-patternです。クラスにコンストラクタやフィールドに8つの依存関係があるかどうかは関係ありませんが、それは常に間違っています。人々は、フィールドを経由するよりも、コンストラクタに依存関係を追加することをもっと嫌っています。それはあなたの脳への信号として機能し、しばらく停止してコード構造について考えるべきです。

短所:

  • その他のコード(しかし、現代のIDEの痛みを緩和します)。

基本的に、フィールド注入は反対である。

関連する問題