目次
典型的な面接の質問: プロパティ注入、コンストラクター注入、セッター注入の違いは何ですか?
I.はじめに:
前回のブログでは、Spring コア プロジェクトの一般的なプロセスについて説明しました。
プロジェクトを作成する - 「Springコンテナにオブジェクトを格納する」 - SpringコンテナからBeanオブジェクトを取り出す
しかし、前の記事で説明したプロセスは依然として煩雑です。オブジェクト アクセスを実現するもっと簡単な方法はあるでしょうか?
もちろんありますので、見てみましょう!
まず第一に、Spring プロジェクトの作成です。これについては何も言うことはありません。前回のブログの手順に従うだけです。
ただし、注意: 以前のブログと比較して、Bean オブジェクトの格納をより簡単に実現するために、Spring の設定ファイルが変更されました (オブジェクトを Spring に格納する)
変更されたスプリング構成ファイル
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:content="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <content:component-scan base-package="在对象储存中,要扫描的路径"></content:component-scan> </beans>
次に、Bean オブジェクトを格納します
まず、Bean オブジェクトを格納する方法を実装したことを思い出してください。
以前に Bean を保存したときは、次の図に示すように、spring-config に Bean 登録コンテンツの行を追加する必要がありました。
この Bean の入金方法はあまり良くありません。
1. 構成ファイルに Bean オブジェクトを手動で追加する必要がある
2. 構成ファイルに問題がある場合、デバッグは容易ではありません。
これで、Spring 構成ファイルに格納したい Bean オブジェクトを 1 つずつ追加する必要がなくなりました。私たちは直接:
スキャンパスを構成ファイルに追加するだけで十分だと思いますか?
いいえ、クラスにアノテーションを追加する必要があります。再スキャンのプロセス中、アノテーションが付けられたクラスのみが Spring に正常に保存されます。
これにより、アノテーションの概念が得られます。
2 つの方法があります:
1. 5 つのカテゴリのアノテーションを使用して実装します。1. @Controller [コントローラー - コントローラー]
2. @Service [サービス - サービス]
3. @Repository [リポジトリ - ウェアハウス]
4. @Configuration [構成 - 構成/レイアウト]
5. @Component [コンポーネント - コンポーネント]
以上注釈の 5 つのカテゴリのいずれか 1 つで、Spring に Bean を保存できます。2. @Bean メソッドアノテーションにより、Bean を Spring に格納することもできます。
注釈の 5 つのカテゴリ
上記では @Service アノテーションを使用しましたが、他の 4 つのアノテーション @Controller と @Repository は同じです。
補足 1:
これら 5 つのカテゴリのアノテーションの使用法は非常に似ているのに、なぜ 5 つの異なるアノテーションに分けられているのでしょうか? アノテーションを一つに統一するのは良くないのでしょうか?
この質問に答えるには、まずソフトウェア エンジニアリングの知識を理解する必要があります。
私が「ソフトウェア階層化」の定義について話す理由は、「なぜ 5 つのアノテーション カテゴリがあるのか」についての後の説明への道を整えるためです。
見てみましょう
これら 5 つのカテゴリの注釈はソフトウェア階層化の異なる層に対応するため、実装される機能は異なります。
注釈が 5 つのカテゴリに分けられている理由を理解するのは難しくありませんが、
補足 2:
まだ疑問があるかもしれません:なぜですか? Spring は次の構成でなければなりませんか?
そのような構成がない場合は何を意味しますか? ?
Spring プロジェクトでは、クラスは 2 つのタイプに分類できます。
1. 制御の反転が必要なクラス、およびその「ライフサイクル」が Spring に渡されて管理されるクラス。[例:UserController]
2. Spring にクラスを保存する必要はありません。
大規模なプロジェクトがあり、Spring に保存する必要があるクラスと Spring に保存する必要のないクラスが 50 対 50 で分割されているとします。
これでは問題が発生します。
このコード行をルート ディレクトリに記述しない場合、
Spring はすべてのクラスをスキャンして、どのクラスが存在するかを確認します。
しかし!プロジェクト内の Spring に保存する必要があるクラスは 50% のみです。
つまり、Spring は、Spring に保存する必要のないクラスをチェックするために 2 倍の時間を無駄にします。
したがって、Spring の効率を向上させるには、スキャンするディレクトリを指定する必要があります。
このディレクトリに、Spring に保存する必要があるクラスが存在することを確認してください。
このようにして、Spring は対応するディレクトリ内のクラスをスキャンするだけで済みます。
@Beanメソッドのアノテーション
以上、Spring では 5 種類の主なアノテーションと Bean メソッドを使用して Bean オブジェクトの単純な保存を実装しました。では、Spring から Bean オブジェクトを簡単に取得するにはどうすればよいでしょうか?
3. Beanオブジェクトを取得する
Bean オブジェクトの取得はオブジェクト アセンブリとも呼ばれます。これは、オブジェクトを取り出して特定のクラスに入れることであり、オブジェクト インジェクションと呼ばれることもあります。
オブジェクト注入は実際には Spring の DI (依存性注入) です。
IoC と DI は Spring の 2 つの最も重要な概念であり、そのうち IoC (Inversion of Control) は制御の反転の概念であり、DI (Dependency Injection) はその (IoC) 固有の実装です。では、DI は依存関係の注入を実装する方法は何通りあるのでしょうか? これらの注入方法はどう違うのでしょうか?
Spring で @Autowired を介して依存関係の注入を実装するには、次の 3 つの一般的な方法があります。
- フィールドインジェクション;
- Setter 注入(Setter Injection);
- コンストラクターのインジェクション。
属性インジェクション
したがって、次のように結論付けることができます。
プロパティ注入に @Autowired を使用する場合
、注入されたオブジェクトが Spring に複数回格納されると、プロパティの型だけでは一致する Bean が見つかりません。属性の変数名をBeanNameに変更し、BeanNameに基づいて一致するオブジェクト(Bean)を見つけて属性インジェクションを行う必要があります。
方法は複数ありますが、上記の「Beanの名前を正確に記述する」方法が最も簡単で効率的です!非常に簡単ではありませんか。Spring のコンテキスト オブジェクトや getBean メソッドを取得する必要がなく、アノテーションを通じて直接対応する Bean を取得できます (Spring から Bean を取り出す)。
別の例を見てみましょう
同じ種類の Bean が複数ある場合、一意でない Bean 例外が発生する可能性があります。
では、この問題をどうやって解決すればよいでしょうか?
ふたつのやり方:
1. 属性名をクラス内のメソッド名 Student1 または Student2 に変更します。
2. @Qualifier を使用して Bean をフィルタリングする
長所と短所
アドバンテージ:
属性インジェクションの最大の利点は、実装が簡単で使いやすいことです。変数にアノテーション (@Autowired) を追加するだけで、新しいオブジェクトを使用せずに、挿入されたオブジェクトを直接取得できます (これは関数とDIの魅力。)
欠点:
- 機能上の問題: 不変オブジェクトを挿入できません (最終的に変更されたオブジェクト - 初期化できません)。
- 普遍性の問題: IoC コンテナにのみ適しています。
- 設計原則の問題: 単一の設計原則に違反することはより簡単です (使用の利便性のため、プロパティ注入はプログラム内で広範囲に使用される可能性があります)。
セッターインジェクション
メリットとデメリットの分析
上記のコードからわかるように、Setter インジェクションはプロパティ インジェクションよりもはるかに面倒です。
アドバンテージ:
Setter インジェクションに利点があるとすれば、まず矢面に立たされるのは、各 Setter が 1 つのオブジェクトのみを対象とするため、単一責任の設計原則に完全に準拠していることです。
欠点:
しかし、その欠点も明らかであり、その欠点は主に次の 2 つの点に反映されています。
- 不変オブジェクトは挿入できません (最終的に変更されたオブジェクト - コンストラクターを通じて初期化できません)。
- 挿入されたオブジェクトは変更可能です (setter メソッドは複数回呼び出すことができます)
コンストラクターインジェクション
メリットとデメリットの分析
アドバンテージ:
前の 2 つの注入方法と比較して、コンストラクター注入は不変オブジェクトを注入でき、一度だけ実行され、注入されたオブジェクトがいつでも変更される Setter インジェクションのようなものはなく、その利点は次のとおりです。
- 注入可能な不変オブジェクト (コンストラクターで初期化)。
- 注入されたオブジェクトは変更されません (クラスでは、コンストラクターは 1 回しか呼び出すことができません)。
- 注入されたオブジェクトは完全に初期化されます。
- より多用途です (つまり、IoC コンテナーと非 IoC コンテナーの両方に使用できます)。
欠点:
構築メソッドでは複数のパラメータを渡すことができるため、単一性の原則に違反しやすい
典型的な面接の質問: プロパティ注入、コンストラクター注入、セッター注入の違いは何ですか?
@Resource と @Autowired の違い
@Autowired は spring によって提供されるアノテーション、@Resource は jdk によって提供されるアノテーションです
1. 使い方の違い
- @Autowired は、プロパティ インジェクション、コンストラクター インジェクション、および Setter メソッド インジェクションをサポートします。
- @Resource: プロパティ インジェクションと Setter メソッド インジェクションをサポートします。コンストラクターの注入はサポートされていません。
2. @Resource の属性注入は、@Autowired の属性注入よりも使いやすいです。@Resource には設定できるプロパティが多数あるのに対し、@Autowired には value プロパティが 1 つしかないためです。
属性がたくさんあるということは、他の多くの機能が使用できることを意味します。
たとえば、上記の同じタイプの Bean が複数ある場合、一意でない Bean の例外が発生する可能性があります。@ Autowired の場合、Bean をフィルタリングしてマージするための追加の @Qualifier も必要です。
そして @Resource は次のことを直接行うことができます。