Spring 5.x Source trip thirteen finishBeanFactoryInitialization and getMergedLocalBeanDefinition

Complete the initialization of BeanFactory

As already finished analysis invokeBeanFactoryPostProcessorsand registerBeanPostProcessors, and then in the middle of some of the core is not the skip, the last remaining piece of the core, there is a single example of the beancreation, and also the most central places, we analyze it slowly, omitted non-core code, in fact, only one code.

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

DefaultListableBeanFactory的preInstantiateSingletons

First of all you will get beanDefinitionNames, and then create a copy, there is a change in time to avoid the use of. Then traverse beanname, if non-abstract, singleton instance of non-lazy loading, if it is FactoryBean, then it acquired FactoryBeaninstance, if you get to this example, it is determined whether to immediately load FactoryBeaninstance is created, the default is not created when needed create. Here we must pay attention to get FactoryBeantheir name is beanNamepreceded by &the symbol, if it is acquired FactoryBeaninstance is created, the name is beanName. If it is not FactoryBeanthe type of go directly to the acquisition.
Here Insert Picture Description
After the acquisition is completed, all patients but also for single processor, if it is SmartInitializingSingletonthe type of conduct on afterSingletonsInstantiatedthe call.

@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 practical examples

Creating a FactoryBeanclass UserDaois an interface, UserDaoImpleit is the implementation class.

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

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

A test - 获取testFactoryBeanto get is TestFactoryBeanthe getObject()instance created:

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

Here Insert Picture Description
Test two - 获取&testFactoryBeanto get TestFactoryBeanitself:

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

Here Insert Picture Description

getMergedLocalBeanDefinition merger bean definition

In fact, this very early, the front did not say, now speak more appropriate. Why should this not have a beandefinition of what, I think this may be in order to unify process , many places are acquired after the merger beandefined to deal with, because beanthe definition may be modified , when dealing with the want to handle the latest , you will probably need to modify beanthe definition once again merged into a unified RootBeanDefinition. Because BeanDefinitionthere are different implementation classes, but there will certainly be a more comprehensive subclass is RootBeanDefinition, but he also provides a constructor and a deep copy cloning method, you can pass other BeanDefinitionsub-categories and create a new one RootBeanDefinitionto the properties of the deep copy.
Here Insert Picture Description
Here Insert Picture Description
Let's look at the source code of this method, starting with the definition of merger acquisition, if found, and does not need to merge the direct return, otherwise merge. staleAttribute indicates whether or not to merge, the default is needed.

	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));
	}

When do you need to set it merge

When it stale=truedoes, that is to say the need for consolidation, we take a look, first AbstractBeanFactoryof clearMergedBeanDefinition:
Here Insert Picture Description
he used it was where, in AbstractBeanFactorythe markBeanAsCreated, and said the comments here, let him merge it because we are unified processing, are combined to determine that, so at this time to be created, may need the latest bean definitions, so to merge once, to get the latest bean definition:
Here Insert Picture Description
Another place is invokeBeanFactoryPostProcessorsthe last:
Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
that BeanFactoryPostProcessorprocess after is finished, beanthe definition may change, so I need to merge in order to ensure that the merger is the latest .

Merge summary

Why are summarized under the merger simply means that springyou want to process beandefinitions can be unified, but many beandefinitions are different subclasses implementation class, and may be modified processor, so springyou need to visit beanto merge when defined, on the one hand the latest merger definition, one can centrally, in fact, is my guess.

Write so much, it seems to say a few amplification, ashamed ah, but that's okay, can understand just fine, not too white I wrote, back next time we continue it.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105014627