/**
* 冻结所有bean定义,表示已注册的bean定义将不会被进一步修改或后处理。
* <p>This allows the factory to aggressively cache bean definition metadata.
*/
void freezeConfiguration();
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
前面几篇文章分析代码里面都动不动会提到是否冻结
boolean isConfigurationFrozen();
@Override
public boolean isConfigurationFrozen() {
return this.configurationFrozen;
}
private volatile boolean configurationFrozen;
这两个方法都是beanFactoryPostProcessor的扩展点的方法。
也就是这个属性,是否为true,true就是表示已经被冻结了,也就是调用这个freezeConfiguration可以将其冻结。
那么什么是冻结呢?冻结啥呢?冻结有什么用呢?咱们接着看
所谓的冻结就是spring不会标识一个bd已经过期;也就是你如果对一个bd更改了属性(在冻结之后);不会被合并了;因为你修改了bd,但是spring不会觉得这个bd已经过期(判断已经冻结,不会合并);故而修改的不会生效;
可以看看Spring会在哪调用这个冻结
finishBeanFactoryInitialization(beanFactory);
真正被调用是在refresh()的这个方法里
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
//冻结所有的beanDefinition
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
//实例化所有的单例bean
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
前面的代码先不管,就看后面两个,可以看到在这里面,是先进行了冻结,再调用下面的函数,实例化所有的单例bean。
那么为什么要冻结呢?
这个就要看我前面写的文章了,在很多地方都有提到这个冻结的判断,
@Override
public void clearMetadataCache() {
//表示mergedbdmap当中的bd过期了 没有冻结
super.clearMetadataCache();
this.mergedBeanDefinitionHolders.clear();
clearByTypeCache();
}
这个方法也是beanFactoryPOSTProcessor的扩展点方法
这个方法里面的clearMetadataCache
public void clearMetadataCache() {
this.mergedBeanDefinitions.forEach((beanName, bd) -> {
//如果被冻结则不会进if,表示不会重写merged
//会调用子类的这个方法
if (!isBeanEligibleForMetadataCaching(beanName)) {
//改这个标识,默认为false
bd.stale = true;
}
});
}
protected boolean isBeanEligibleForMetadataCaching(String beanName) {
//判断是否被冻结或者这个bean是否已经开始被创建了。
return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName));
}
这个就是通过是否已经冻结了来判断,如果被冻结了,就不会进入if去改bd的stale,这个东西,又和merge合并有关系。
所以前面写的文章要连起来看代码多想想,很多都是连在一起的
那么这个stale可以在我写的mergedBeanDefinition中会有发现,
在这个方法中会有判断,判断bd的stale,如果为false,则不用合并直接返回bd。
所以可以明白了吧,这个stale就是一个标识,标识此bd是否需要再合并。
而冻结,就能够让bd的stale为false,也就是不用再合并。
合并这个可以看mergedBeanDefinition文章。你会发现,其实在Spring里面,有多个bdmap。而为啥spring要这么搞,我现在也不太清楚,可能跟业务逻辑有关系吧。