Spring @Component で @Autowired を使用すると、Spring はコンポーネントのインスタンス化ごとに autowire 候補を決定します。Spring が ApplicationContext 内で Bean 定義を一度だけ作成し、それを再利用しないのはなぜですか? そうする方法はありますか?
5 に答える
AutowiredAnnotationBeanPostProcessor
はBeanPostProcessor
ではなく であるBeanFactoryPostProcessor
ため、設計上、Bean 定義を編集できません。それを別の方法で実装すると、期待される機能が損なわれます。
public class MyBean{
@Autowired(required=false)
public void setOtherBean(OtherBean o){this.otherBean=o;}
private OtherBean otherBean;
}
使用可能なインスタンスがないOtherBean
場合、何も接続されませんが、使用可能になるとすぐに (プログラムで簡単に接続できます)、次のMyBean
インスタンス (スコープがシングルトンでない場合) は新しいインスタンス (OtherBean
以前は使用できませんでした) を取得します。
これが私が以前に遭遇したユースケースであると言っているわけではありませんが、これは有効なユースケースであり、あなたが提案したように物事が機能すると壊れるでしょう。
はい: スコープを別のものに設定すると、Spring はコンポーネントを再利用します (つまり、プロトタイプ、セッション、または要求を使用してはなりません)。秘訣は、2 つのBean を使用することです。変更されないすべてのものを含む 1 つです。そして、セッション/リクエストにアタッチされ、単一の依存関係を持つ 1 つの Bean: 最初の Bean。
Bean が十分に「静的」である場合のルールがないため、Spring はこれを行うことができません。開発者はそれを決定する必要があります。
[編集] DAO/サービス Bean で Bean の静的部分 (時間の経過とともに変化しないもの) を収集する必要があります。次に、その Bean を@Component
-> 1 つのルックアップで使用します。
検索を高速化するには、コンポーネントに名前を付けます。タイプベースのルックアップの場合、Spring はコンテキスト全体を反復する必要があります (複数の Bean が一致する可能性があるため) が、名前/ID ベースのルックアップはマップ内の単なるルックアップです。
Bean に名前を付けるには、 で指定する@Context
か、 を使用します@Bean(name="name")
。コンテキストから使用する Bean を Spring に伝えるには、@Resource(name)
またはを使用します@Qualifier("businessObject")
。
リクエスト/セッション スコープ Bean で @Scope アノテーションの proxyMode 属性を設定します。Spring は、自動配線されるプロキシを作成します。プロキシは、メソッドが呼び出される実際の Bean を検索します。
Provider
手動の代替手段は、プロトタイプスコープの Bean を提供するシングルトンスコープを Bean に注入することです。
これは、プログラマーが行う作業が増えることを意味しますが、パフォーマンスへの影響は解消されます。
ベスト プラクティスは、サービス クラス、コンポーネント、DAO などをシングルトンとして使用し、アプリケーション コンテキストにインスタンスを 1 つだけ持つことです。@Component アノテーションにより、インスタンスだけがコンポーネント スキャン プロセスで検出されます。 -春のコンテキストでインスタンスをスキャンして生きています。例えば:
@Component
public class StudentDAO {
@Override
public String toString() {
return " inside StudentDAO";
}
}
StudentDAO はデータ アクセス オブジェクトであり、ベスト プラクティスでは、コンテキスト内でこのサービス コールの複数のインスタンスは必要ありません。基本的にサービスクラスです。これは、シングルトンの完全な候補です。このオブジェクトのインスタンスが 1 つしかない場合でも、オートワイヤリングは同様に効率的に機能します 8-) .しかし、シングルトン メソッドへのアクセスには注意し、スレッドの望ましくない影響を防ぐために、メソッドを同期済みとしてマークすることを決定する必要があります。