Springソースコード分析-Springキャッシュと循環依存の問題

序文

前回の記事の分析から、春にBeanを作成およびインスタンス化するプロセスにはより多くのリンクがあり、パッケージングがより深いことがわかります。getBeanのたびに多くのリンクが必要な場合、多くのメモリオブジェクトと計算ロジックが生成されるだけではありません、さらに重要なことに、一部のシーンではオブジェクトの依存関係の問題、特に循環依存関係の問題を解決できません。したがって、Spring自体がこの問題を考慮に入れており、Beanの作成プロセスに関連するキャッシュ設計がいくつかあります。今日は、キャッシュによってどのように解決されるかを見ていきます。

シーンをキャッシュ

シナリオ1. getBean()で初めて
Springソースコード分析-Springキャッシュと循環依存の問題
Bean 取得する場合、上図のプロセスに従って1次または2次キャッシュから取得され、取得された場合は直接返されます。そうでない場合は、3次キャッシュから直接取得します。3次キャッシュにキャッシュされたオブジェクトがある場合、キャッシュされたbeanFactory .getObject()を介して直接Beanを取得し、3次キャッシュを削除して、取得したBeanを2次キャッシュに書き込みます。キャッシュしてからオブジェクトを返します。
Springソースコード分析-Springキャッシュと循環依存の問題
Springソースコード分析-Springキャッシュと循環依存の問題
シナリオ2.最初のcreateBean()
Springソースコード分析-Springキャッシュと循環依存の問題
Springソースコード分析-Springキャッシュと循環依存の問題
のdoCreateBean()プロセス中に、事前にBean設定を公開できる場合(デフォルトで有効)、3次レベルキャッシュ(beanFactoryオブジェクト)
Springソースコード分析-Springキャッシュと循環依存の問題
Springソースコード分析-Springキャッシュと循環依存の問題
が作成されます。3次レベルキャッシュの作成時に2次レベルキャッシュが削除されるのはなぜですか?キャッシュ?2次キャッシュ内のオブジェクトは3次キャッシュから取得されるため、3次キャッシュが更新されると、古い2次キャッシュデータが同時に削除され、キャッシュデータの不整合の問題が回避されます。

循環依存

Aオブジェクトでは、Bオブジェクトへの参照が保持されます。同様に、Bオブジェクトでは、Aオブジェクトへの参照もサポートされます。この種の循環依存は、次の2つの状況に分けられます。1。Aオブジェクトでは、BオブジェクトはAオブジェクトのメンバー変数として使用されます。2。Aオブジェクトでは、BオブジェクトはAオブジェクトの構築パラメーターに依存します。2つのメソッドが相互に影響すると、リングの参照シーンは注意が必要です。
Springソースコード分析-Springキャッシュと循環依存の問題
上記のスクリーンショットは最初のケースに属し、Springはこのケースのみを考慮します。この場合、スプリングは通常の参照と見なされますが、それ以外の場合、スプリングはサポートせず、この場合は直接例外をスローします。
Springソースコード分析-Springキャッシュと循環依存の問題
Springソースコード分析-Springキャッシュと循環依存の問題

解決

では、スプリングは上記の最初の循環依存状態をどのように解決しますか?この問題は、3レベルのキャッシュメカニズムを構築することで完全に解決されます。具体的な解決プロセスについては、以下のフローチャートを参照してください。
Springソースコード分析-Springキャッシュと循環依存の問題
上記の解決フローチャートと投稿されたキャッシュソースコードによると、詳細な説明は次のとおりです。

  1. CircularRefAがインスタンス化されると、まずキャッシュからインスタンスBeanを取得します。
  2. キャッシュの3つのレベルにオブジェクトがない場合は、getSingleton()を呼び出してインスタンスを作成します。
  3. 匿名クラスを呼び出してインスタンスを作成しますcreateBean();
  4. コンストラクターを介してCircularRefAオブジェクトをインスタンス化します(オブジェクトの依存関係プロパティとメンバーはインスタンス化されません。つまり、この時点ではCircularRefBオブジェクトはnullです)。
  5. CircularRefAに対応するobjectFactoryオブジェクトをキャッシュする3次レベルのキャッシュを作成します。
  6. CircularRefAで依存性注入を実行してから、CircularRefBオブジェクトのgetBean()操作をトリガーします。
  7. プログラムは再帰的にステップ1 ...ステップ6に入ります。
  8. 同じことがステップ6に進んだら、CircularRefBのCircularRefAに依存関係注入を実行して、getBean()操作をトリガーします。
  9. このとき、CircularRefAへの参照は3次キャッシュから取得できます(スケルトンにすぎません)ので、CircularRefAが挿入されます。
  10. CircularRefBのインスタンス化が完了するとすぐに、依存関係の注入によってCircularRefAのCircularRefBメンバー変数に割り当てられます。
  11. 最後に、2つのオブジェクト、CircularRefAとCircularRefBがインスタンス化されます(これらは互いの参照を保持しており、この時点でも割り当てられます)。

わかりました、ここでわかりますか?Springの3レベルのキャッシュメカニズムの設計は非常に興味深いものです。興味のある人はソースコードに行くことができます。
最後に、明確な結論を出す必要があります:上記の最初のケースではbeandefintionのScope = Singletonタイプのみがキャッシュを実行し、循環依存をサポートできます。他のタイプの循環依存が発生する限り、Springは直接例外をスローします。Springが他のケースでソースコードをサポートしない理由については、多かれ少なかれ考えることができます。

おわりに

スプリングキャッシングと循環依存関係に関する問題は、最初にここで共有されます。これについて質問がある場合は、コメント欄に直接メッセージを残すことができます。スプリングソースコードのより乾燥した商品に引き続き注意してください!

おすすめ

転載: blog.51cto.com/14815984/2532622