依存性注入を使用する場合、通常は3つの方法があります。
-
コンストラクターを介して注入します。
-
セッターメソッドを介して注入します。
-
ファイルされた変数を介して注入します。
コード例:
- コンストラクタ
private DependencyA dependencyA;
private DependencyB dependencyB;
private DependencyC dependencyC;
@Autowired
public DI(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC) {
this.dependencyA = dependencyA;
this.dependencyB = dependencyB;
this.dependencyC = dependencyC;
}
- セッター
private DependencyA dependencyA;
private DependencyB dependencyB;
private DependencyC dependencyC;
@Autowired
public void setDependencyA(DependencyA dependencyA) {
this.dependencyA = dependencyA;
}
@Autowired
public void setDependencyB(DependencyB dependencyB) {
this.dependencyB = dependencyB;
}
@Autowired
public void setDependencyC(DependencyC dependencyC) {
this.dependencyC = dependencyC;
}
- フィールド
@Autowired
private DependencyA dependencyA;
@Autowired
private DependencyB dependencyB;
@Autowired
private DependencyC dependencyC;
3つの方法の違いの要約:
-
コンストラクターベースの注入により、依存性注入の順序が修正されます。このメソッドでは、Beanオブジェクト間に循環依存関係を作成できません。この制限は、実際には、コンストラクターを使用して注入することの利点です。注入すると、Springは循環依存の問題を解決できます。
-
セッターベースの注入
では、初期化時ではなく、オブジェクトを注入する必要がある場合にのみ依存性を注入するのに役立ちます。一方、コンストラクターベースの注入を使用する場合、CGLIBはプロキシを作成できないため、インターフェイスベースのプロキシまたは仮想パラメータレスコンストラクタを使用します。 -
多くの学生がインジェクションのためにメンバー変数に直接注釈を書くことを選択すると思います。これまで見てきたように、この方法は非常に見栄えがよく、短く、読みやすく、冗長なコードを必要とせず、保守が簡単です。
短所:
-
コンストラクターを使用して注入する場合、より明白な欠点の1つは、多くのオブジェクトを注入する必要がある場合、コンストラクターが非常に冗長で見苦しく見えるため、美しさと読みやすさに大きく影響します。また、保守がより困難になります。 ;
-
注入するsetterメソッドを選択する場合、オブジェクトを最終にすることはできません。
-
フィールド変数にインジェクションを実装する場合
a。これはJavaBean仕様に準拠しておらず、nullポインタを引き起こす可能性があります。
b。同時に、オブジェクトを最終としてマークすることはできません。
c。クラスはDIコンテナと高度に結合されているため、外部で使用することはできません。
d。クラスはリフレクションなしでインスタンス化することはできません(たとえば、単体テストで)。統合テストに似たDIコンテナーを使用してインスタンス化する必要があります。
…
来自Spring官方文档的建议:
など1️⃣Spring3.xでは、Springチームはセッターを使用して注入することを推奨しています。大まかに言えば、特に属性がオプションの場合、多数のコンストラクターパラメーターは非常に面倒な場合があります。setterメソッドを使用すると、クラスのオブジェクトを後で再構成または再注入できます。すべての依存関係を提供するということは、オブジェクトが常に完全に初期化されたクライアントクライアント(呼び出し)を返すことを意味します。欠点は、オブジェクトが再構成と再注入に適さなくなることです。
2️⃣Spring4.xでは、Springチームは、コンストラクターの代わりにセッターをインジェクションに使用することを推奨しなくなりました
Springチームは通常、インジェクションにコンストラクターを使用することをお勧めします。コンストラクターを使用すると、アプリケーションコンポーネントを不変オブジェクトとして実装でき、必要な依存関係が空にならないようにするためです。さらに、コンストラクタインジェクションコンポーネントは常に完全に初期化されたクライアントクライアント(呼び出し)を返します。コンストラクターパラメーターの数が多いと、コードの習慣が悪くなり、見た目も悪くなることに注意してください。つまり、クラスの責任が多すぎる可能性があるため、関心の分離に適切に対処するためにリファクタリングする必要があります。
setterメソッドは、主に、クラスで適切なデフォルト値を指定できるオプションの依存関係にのみ使用する必要があります。それ以外の場合は、依存関係が使用されている場所でnull以外のチェックを実行する必要があります。セッターインジェクションの利点の1つは、セッターメソッドを使用すると、クラスのオブジェクトを後で再構成または再インジェクトできることです。
Spring 4.3の新機能: Spring 4.3以降、クラスにコンストラクターが1つしかない場合、Springは暗黙の自動インジェクションを実装します。コードは次のとおりです。
@Service
public class FooService {
private final FooRepository repository;
@Autowired
public FooService(FooRepository repository) {
this.repository = repository
}
}
春4.3以降:
@Service
public class FooService {
private final FooRepository repository;
public FooService(FooRepository repository) {
this.repository = repository
}
}
ご覧のとおり、コンストラクターの@Autowiredアノテーションを削除しました。テストの結果、プログラムは正常に実行でき、リポジトリの依存関係が正常に挿入されていることがわかりました。
総括する:
-
必須の依存関係、またはターゲットが不変の場合は、コンストラクターインジェクションを使用します(コンストラクターは可能な限りインジェクションするために使用されると言わなければなりません)
-
オプションまたは変更可能な依存関係は、セッターインジェクションを使用します(コンストラクターをセッターと組み合わせてインジェクトすることをお勧めします)
-
ほとんどの場合、フィールドインジェクションは避けてください(ほとんどの学生は反対意見を持っていると思います。結局のところ、この方法は非常に簡単に記述できますが、その欠点は実際にこれらの利点よりはるかに大きいです)
-
Spring 4.3以降の学生は、コンストラクターの暗黙的なインジェクションを試すことができます。この方法でインジェクションした後、コードはよりエレガントで独立し、Springへの依存度が低下します。