春の5.xのソースの旅13 finishBeanFactoryInitializationとgetMergedLocalBeanDefinition

たBeanFactoryの初期化を完了

すでに完成し、分析したようinvokeBeanFactoryPostProcessorsregisterBeanPostProcessorsした後、コアの一部の途中でスキップ、コアの最後の残りの部分ではない、そこの単一の例でbean作成は、また、最も中心的な場所、私たちは省略し、ゆっくりとそれを分析します非コアコード、実際には、唯一のコード。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		...
		//准备实例化单例
		// Instantiate all remaining (non-lazy-init) singletons.
		beanFactory.preInstantiateSingletons();
	}

DefaultListableBeanFactory的preInstantiateSingletons

まず第一にあなたが得るだろうbeanDefinitionNamesし、そのコピーを作成し、使用を避けるために時間に変更があります。そして、トラバースbeanそれがある場合、名前、非抽象場合、非遅延読み込みのシングルトンインスタンスは、FactoryBean、それは取得しFactoryBeanますが、この例に取得する場合、すぐにロードするかどうかを決定し、インスタンスをFactoryBeanインスタンスが作成され、必要なときに、デフォルトでは作成されません作成されました。ここでは、取得するために注意を払う必要がありますFactoryBean彼らの名前がさbeanNameが先行し&、それを取得した場合には、シンボルFactoryBeanインスタンスが作成され、名前がありますbeanNameそれがない場合にはFactoryBean取得に直接行くのタイプ。
ここに画像を挿入説明
買収が完了した後、すべての患者だけでなく、単一のプロセッサのための、それがある場合SmartInitializingSingletonの行動のタイプafterSingletonsInstantiatedのコールが。

@Override
	public void preInstantiateSingletons() throws BeansException {
		...
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);//创建一个副本,让原始的还能继续注册bean定义
		//触发非懒加载的单例bean初始化
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//合并父类的bean定义
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//非抽象,单例,非懒加载
				if (isFactoryBean(beanName)) {//是否是FactoryBean类型的,是的话要加前缀获取
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//获取FactoryBean
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;//是否需要立即创建FactoryBean中的bean
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {//非FactoryBean
					getBean(beanName);
				}
			}
		}
		//所有单例的还要进行处理器处理
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

FactoryBeanの実用的な例

作成FactoryBeanクラスはUserDaoインターフェースである、UserDaoImpleそれは実装クラスです。

@Component
public class TestFactoryBean implements FactoryBean<UserDao> {
	@Override
	public UserDao getObject() throws Exception {
		return new UserDaoImple();
	}

	@Override
	public Class<?> getObjectType() {
		return UserDao.class;
	}
}

テスト- 获取testFactoryBean取得するには、ある作成されたインスタンス:TestFactoryBeangetObject()

 @Test
    public void FactoryBeanTest() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(TestFactoryBean.class);
        applicationContext.refresh();
        Object obj=  applicationContext.getBean("testFactoryBean");
        System.out.println(obj);
    }

ここに画像を挿入説明
テスト2 - 获取&testFactoryBean取得するTestFactoryBean自分自身を:

 @Test
    public void FactoryBeanTest() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(TestFactoryBean.class);
        applicationContext.refresh();
        Object obj=  applicationContext.getBean("&testFactoryBean");
        System.out.println(obj);
    }

ここに画像を挿入説明

getMergedLocalBeanDefinition合併Bean定義

実際には、これは非常に早い、フロントは今、より適切なを話し、言いませんでした。なぜ、これは持つべきではないbean、私はこれがためにかもしれないと思うものの定義統一プロセス、多くの場所は、合併後に取得されているbeanので、対処するために定義されたbean定義が可能に変更することを扱うとき、最新のを処理したいと、あなたはおそらく変更する必要がありますbean再び統一に合併後の定義をRootBeanDefinitionのでBeanDefinition別の実装クラスがありますが、確かに、より包括的サブクラスがあるだろうRootBeanDefinitionが、彼はまた、コンストラクタとディープコピーのクローニング方法を提供し、あなたは他の渡すことができBeanDefinition、サブカテゴリーをして、新しい作成RootBeanDefinition深いの性質にしますコピー。
ここに画像を挿入説明
ここに画像を挿入説明
このメソッドのソースコードを見てみましょうが、見つかった場合、合併買収の定義から始まり、そしてそれ以外の場合は、直接のリターンをマージマージする必要はありません。stale属性はデフォルトが必要とされ、マージするか否かを示しています。

	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null && !mbd.stale) {//存在且不需要合并的话就直接返回
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

ときあなたはそれをマージを設定する必要があります

それはときにstale=trueありません、それは統合の必要性は、私たちはまず、見てみると言うことですAbstractBeanFactoryclearMergedBeanDefinition
ここに画像を挿入説明
彼はそれを使用したところ、中、私たちは統一されているので、ここでのコメントは、彼にそれをマージさせました処理し、その作成するこの時点では、最新のBean定義を取得するには、その一回マージする、最新のBean定義が必要になる場合があり、それを決定するために結合される。別の場所にある最後:そのプロセス終了後、定義はので、変更される可能性があり、私は合併が最新であることを確実にするためにマージする必要がありますAbstractBeanFactorymarkBeanAsCreated
ここに画像を挿入説明
invokeBeanFactoryPostProcessors
ここに画像を挿入説明
ここに画像を挿入説明
ここに画像を挿入説明
BeanFactoryPostProcessorbean

マージの概要

なぜ合併の下に要約されているだけであることを意味springしますが、プロセスに必要beanな定義を統一することができますが、多くのbean定義が異なるサブクラスの実装クラスであるので、プロセッサを変更することができるspring、あなたが訪問する必要がbean定義されたときにマージする1手、最新の合併で、定義は、1缶の中央、実際には、私の推測です。

書き込みも多いので、それは恥ずかしいああ、いくつかの増幅を言うようですが、それは大丈夫だ、あまりにも白私は戻って、我々はそれを継続する次の時間を書いて、うまくはない理解することができます。

さて、今日ここに、私たちは自分自身の学習、限られた容量を理解し、偉大な神は見スプレーしないで、言い訳してください、助けの調査に希望と理解しています。

公開された235元の記事 ウォン称賛74 ビュー30000 +

おすすめ

転載: blog.csdn.net/wangwei19871103/article/details/105014627