@Autowired を使用すると IDEA が警告するのはなぜですか?

IDEA を使用して Spring 関連のプロジェクトを作成する場合、フィールドで @Autowired アノテーションを使用すると、「フィールド インジェクションは推奨されません。」という波線のプロンプトが常に表示されます。このため、私はこの方法を毎日使用しているのではないかと疑問に思います。推奨されていませんか?今日はその理由を深く掘り下げてみることにしました。

ご存知のとおり、Spring フレームワークには、コンストラクター インジェクション、Setter メソッド インジェクション、フィールド インジェクションという 3 つのオプションの依存関係注入メソッドが用意されています。ここでは、これら 3 つの注入方法の使用シナリオを詳しく見ていきます。

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

以下に示すように、コンストラクター インジェクションを使用する場合、プロパティ フィールドを Final に設定できます。コンストラクター注入により、AService がインスタンス化されるとき、注入されたオブジェクトが null にならないように、BService オブジェクトを事前に初期化する必要があります。コンストラクター インジェクションは、オブジェクト間に強い依存関係があるシナリオには適していますが、循環依存関係の問題は解決できません (初期化を完了するには相互に依存する必要があり、解決できない競合が発生するため)。

循環依存関係の問題については、「Spring 循環依存関係とは何か、およびそれらを解決する方法 」を参照することをお勧めします 。この記事では、Spring の循環依存関係の原則と解決策について詳しく説明します。

@Service
public class AService {
    private final BService bService;
​
    @Autowired  //spring framework 4.3之后可以不用在构造方法上标注@Autowired
    public AService(BService bService) {
        this.bService = bService;
    }
}

セッターメソッドのインジェクション

Setter メソッドを注入に使用する場合、Spring はデフォルトの引数なしのコンストラクタを実行して Bean オブジェクトをインスタンス化した後、Setter メソッドを呼び出して依存関係を注入します。このようにして、「required」属性を false に設定できます。これは、注入された Bean オブジェクトが存在しない場合、Spring はエラーを報告せずに注入を直接スキップすることを意味します。

@Service
public class AService {
    private  BService bService;
​
    @Autowired(required = false)
    public void setbService(BService bService) {
        this.bService = bService;
    }
}

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

確かに、フィールドインジェクションは視覚的に非常にシンプルで美しいため、広く採用されています。フィールド注入を使用する場合、Spring コンテナはリフレクション メカニズムを使用して、オブジェクトがインスタンス化された後に注入する必要があるフィールドを設定します。

@Service
public class AService {
    @Autowired
    private  BService bService;
}

IDEA がフィールド インジェクションの使用を推奨しない理由

さまざまな情報源を調べた結果、フィールド インジェクションが推奨されない可能性がある次の重要な理由が見つかりました。

  1. null ポインタ例外が発生する可能性がある: Spring コンテナを使用せずにオブジェクトが作成され、パラメータなしのコンストラクター メソッド new を直接使用してオブジェクトを作成する場合、挿入されたオブジェクトを使用すると null ポインタ例外が発生する可能性があります。
  2. 最終変更フィールドは使用できません: 最終変更がないとクラス変数の依存関係が生じ、予期しない例外が発生する可能性があります。通常、コンストラクター インジェクションを使用して必須の依存関係を持つ Bean を宣言し、セッター メソッド インジェクションを使用してオプションの依存関係を持つ Bean を宣言できます。
  3. 単一責任の原則に違反しやすくなる可能性があります。これが重要な理由です。フィールド インジェクションを使用すると、クラスにさまざまな依存関係が簡単に導入され、クラスの責任が過剰になる可能性がありますが、多くの場合、開発者がそれを検出するのは困難です。対照的に、コンストラクター インジェクションを使用すると、コンストラクターのパラメーターが多すぎる場合、開発者はクラスをリファクタリングするように求められます。
  4. 単体テストの作成には適さない: 単体テストでは、フィールド インジェクションを使用する場合、依存オブジェクトをモックするためにリフレクションを使用する必要があります。

これらの問題を解決するには、次の代替手段を使用できます。

  • クラスに他の Bean への強い依存関係がある場合は、コンストラクター インジェクションが推奨されます。
  • オプションの依存関係については、Setter メソッド インジェクションを使用して、参照されるオブジェクトがコード内に存在しない可能性のある状況に対処できます。

春の公式態度

Spring の公式ドキュメントでは、依存関係注入セクションでフィールド インジェクションについて明示的に説明していませんが、コンストラクター メソッド インジェクションと Setter メソッド インジェクションに重点を置いています。コンストラクター インジェクションは、依存関係インジェクションの推奨方法とみなされます。これにより、依存オブジェクトの作成時に確実にインジェクションされるため、null ポインター例外やクラスの可変性などの潜在的な問題が回避されます。

Setter メソッド インジェクションは、オプションの依存関係シナリオでも役立ちますが、開発者は依存オブジェクトが存在しない状況に対処する必要があります。

全体として、Spring チームは、多くの点でより安全で信頼性が高いため、コンストラクター インジェクションを使用することを強く推奨します。同時に、適切な依存関係注入方法を選択することで、特定の状況に応じて柔軟に使用することもできます。

要約する

Spring で依存関係の注入を使用する場合は、コンストラクターの注入が推奨されます。コンストラクターインジェクションでは循環依存の問題を解決することはできませんが、循環依存が発生した場合はコード構造の設計に問題がないかを優先する必要があります。もちろん、循環依存関係を使用する必要がある特定のシナリオを除外するわけではありません。その場合、フィールド インジェクションが役立つ可能性があります。

最後に、IDEA を使用するときは、コードに下線が引かれているか黄色で表示されているというリマインダーに注意を払うことが重要であることを強調したいと思います。これらのヒントは、他の人がまとめたベスト プラクティスから学び、自分自身のコーディング スキルを向上させるのに役立ちます。

この記事が最初に公開された場所: https://www.panziye.com/java/7639.html

ご支援ありがとうございます!

おすすめ

転載: blog.csdn.net/mixika99/article/details/132311859