Spring単例でのループ依存処理,三次キャッシュ

3414 ワード

最近springのソースコードを見ていますが、ここではspringのサイクル依存処理を専門に記録しています.
サイクル依存とは何かを簡単に紹介します.ABという2つのクラスがあります.Aがインスタンス化されるときはBのbeanが必要です.Bがインスタンス化されるときもAのbeanが必要です.AB間はサイクル依存です.Springでは、springは単一の例ではなく、サイクル依存性の存在を許さない.次にspringがサイクル依存に対してどのように処理されているかを主に見ます.
Springオブジェクトの初期化は、次の3つのステップに分けられます.
ステップ1:インスタンス化、createBeanInstance、実際には対応するコンストラクションメソッドコンストラクションオブジェクトを呼び出すが、このときコンストラクションメソッドを呼び出すだけで、spring xmlで指定したpropertyはpopulateを行わない
ステップ2:spring xmlで指定したpropertyをpopulateするプロパティ、populateBeanを入力します.
ステップ3:initializeBean、spring xmlで指定したinitメソッドを呼び出すか、AfterPropertiesSetメソッドがループ依存するステップが第1ステップと第2ステップに集中します.
次に、作成プロセスに直接進み、作成プロセスに関連するソースコードを添付します.
Aは、第1ステップのインスタンス化Aを作成し、次の2つのコードを呼び出す.
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

上の第1段のコードはAのObjectFactoryをsingletonFactoriesに追加して、ここは3級のキャッシュで、すでに作成していないAを表示しました
2番目のセグメントコードはAのbean nameをsingletonsCurrentlyInCreationに追加した.
A 2ステップ目を作成し、属性Bを塗りつぶすと、Bが作成されていないことに気づいたので、Bの作成を開始します
Bを作成する最初のステップ、インスタンス化、
2番目のステップでは、属性Aがインスタンス化され、次のコードが呼び出されます.
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //   A    singletonObjects   
		Object singletonObject = this.singletonObjects.get(beanName);
        // A       isSingletonCurrentlyInCreation  true,       beforeSingletonCreation  
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
                    // A              ,    addSingletonFactory     
					ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

このコードが実行されると,属性Aは既に存在する.
その後、Bのステップ3に進み、Bの作成は完了したが、その属性Aは完全に作成されていない.
次にAの2ステップ目と3ステップ目で、Aも作成完了します.
この相互参照を解決する方法は、3つの変数(いずれもMap)に関連するプロセス全体を含む3つのキャッシュ方法と呼ばれます.
singletonObjects:一級キャッシュ、beanName(key)とbeanインスタンス(value)の関係を格納します.ここに格納されているbeanインスタンスは、完全に作成されたbeanインスタンスです.
earlySingletonObjects:二次キャッシュであり、beanNameとbeanインスタンスの関係も格納されます.singletonObjectsとの違いに注意してください.ここに格納されているbeanインスタンスは、作成が完了していないbeanインスタンスです.つまり、beanは作成中であり、ループ参照の問題を解決するために、完全なbeanは作成されていません.singletonFactories:beanNameとbeanファクトリの関係を保存する3段階キャッシュ.レベル3キャッシュがbeanの作成に成功すると、beanはレベル2キャッシュに格納され、beanNameに対応するbeanFactoryはsingletonFactoriesから削除されます.
ObjectFactory:getobject()メソッドがあり、一例beanの作成中にループ依存の問題を解決するためにbeanName対応のObjectFactoryを作成しSingletonFactoiesに入れ、beanを事前に露出する目的を達成します.三次キャッシュgetObject()(レベル3キャッシュ)を取得し、取得した場合:this.earlySingletonObjects.put(beanName, singletonObject);     this.singletonFactories.remove(beanName); 3レベルキャッシュはなぜですか?getEarlyBeanReferenceでは、AwareBeanPostProcessorのようなバックグラウンドプロセッサをサポートし、ユーザーにインタフェース拡張を提供します.
リファレンスhttps://segmentfault.com/q/1010000019485013?sort=created