Spring 5.x Source trip thirteen finishBeanFactoryInitialization and getMergedLocalBeanDefinition
Complete the initialization of BeanFactory
As already finished analysis invokeBeanFactoryPostProcessors
and 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 bean
creation, 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 bean
name, if non-abstract, singleton instance of non-lazy loading, if it is FactoryBean
, then it acquired FactoryBean
instance, if you get to this example, it is determined whether to immediately load FactoryBean
instance is created, the default is not created when needed create. Here we must pay attention to get FactoryBean
their name is beanName
preceded by &
the symbol, if it is acquired FactoryBean
instance is created, the name is beanName
. If it is not FactoryBean
the type of go directly to the acquisition.
After the acquisition is completed, all patients but also for single processor, if it is SmartInitializingSingleton
the type of conduct on afterSingletonsInstantiated
the 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 FactoryBean
class UserDao
is an interface, UserDaoImple
it 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 - 获取testFactoryBean
to get is TestFactoryBean
the 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);
}
Test two - 获取&testFactoryBean
to get TestFactoryBean
itself:
@Test
public void FactoryBeanTest() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(TestFactoryBean.class);
applicationContext.refresh();
Object obj= applicationContext.getBean("&testFactoryBean");
System.out.println(obj);
}
getMergedLocalBeanDefinition merger bean definition
In fact, this very early, the front did not say, now speak more appropriate. Why should this not have a bean
definition of what, I think this may be in order to unify process , many places are acquired after the merger bean
defined to deal with, because bean
the definition may be modified , when dealing with the want to handle the latest , you will probably need to modify bean
the definition once again merged into a unified RootBeanDefinition
. Because BeanDefinition
there 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 BeanDefinition
sub-categories and create a new one RootBeanDefinition
to the properties of the deep copy.
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. stale
Attribute 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=true
does, that is to say the need for consolidation, we take a look, first AbstractBeanFactory
of clearMergedBeanDefinition
:
he used it was where, in AbstractBeanFactory
the 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:
Another place is invokeBeanFactoryPostProcessors
the last:
that BeanFactoryPostProcessor
process after is finished, bean
the 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 spring
you want to process bean
definitions can be unified, but many bean
definitions are different subclasses implementation class, and may be modified processor, so spring
you need to visit bean
to 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.