Spring
源码 - 容器刷新finishBeanFactoryInitialization()
Spring
版本:Spring 5.3.13-release
finishBeanFactoryInitialization()
初始化剩下的非惰性单实例Bean
AbstractApplicationContext#finishBeanFactoryInitialization()
代码:
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*
* 完成这个容器的 BeanFactory 初始化工作, 初始化剩下的单实例 Bean
*/
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.
// 如果 BeanFactory 之前没有注册嵌入值解析器, 则注册默认的嵌入值解析器, 主要用于注解值的解析
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 尽早初始化 LoadTimeWeaverAware Bean, 以便尽早注册他们的转换器
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);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有的 Bean 定义源数据信息。 说明注册的 BeanDefinition 将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化剩余的单实例对象
beanFactory.preInstantiateSingletons();
}
上面的代码做了如下几件事情:
ConversionService
。BeanDefinition
元数据信息。其中preInstantiateSingletons
为初始化剩余的单实例对象。DefaultListableBeanFactory#preInstantiateSingletons()
代码:
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 将所有 BeanDefinition 的名字创建一个集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 触发所有非延迟加载单例 Bean 的初始化, 遍历 BeanDefinition 集合对象
for (String beanName : beanNames) {
// Bean 定义信息的公共抽象类是 AbstractBeanDefinition, 普通的 Bean 在 Spring 解析 Bean 定义信息时实例化出来的是 GenericBeanDefinition
// Spring 上下文包括实例化所有 Bean 使用的 AbstractBeanDefinition 是 RootBeanDefinition
// 使用 getMergedLocalBeanDefinition 方法做了一次转化, 将非 RootBeanDefinition 转换为 RootBeanDefinition 以供后续操作
// 注意, 如果当前 BeanDefinition 存在父 BeanDefinition, 会基于父 BeanDefinition 生成一个 RootBeanDefinition, 然后在将调用 OverrideFrom 子 BeanDefinition 的相关属性覆写进去
// 合并父类 BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 条件判断。非抽象类 && 单例 && 非懒加载, 则开始创建单例对象, 通过调用 getBean(beanName) 方法进行初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否实现 BeanFactory 接口, 如果实现了 BeanFactory 接口, 判断是否立即初始化
// 判断 Bean 是否立即初始化, 根据 Bean 是否实现了 SmartFactoryBean 接口并重写内部方法 isEagerInit 并返回 true
if (isFactoryBean(beanName)) {
// 根据 & + beanName 来获取 IOC 容器中的 Bean 对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
// 进行类型转换
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
// 判断这个 FactoryBean 是否希望立即初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
// 如果希望急切的进行初始化则调用 getBean 方法通过 beanName 获取 Bean 实例对象
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 如果 beanName 对应的 Bean 不是 FactoryBean, 只是普通 Bean, 调用 getBean 方法通过 beanName 获取 Bean 实例对象
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 遍历 beanNames, 触发所有 SmartInitializingSingleton 后初始化的回调
for (String beanName : beanNames) {
// 获取 beanName 对应的单例Bean实例对象
Object singletonInstance = getSingleton(beanName);
// 判断获取的 singletonInstance 单例Bean对象是否实现了 SmartInitializingSingleton 接口
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
// 将获取的 singletonInstance 类型转换为 SmartInitializingSingleton 接口
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
// 触发 SmartInitializingSingleton 实现类的 afterSingletonsInstantiated() 方法
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
在preInstantiateSingletons()
方法中,Spring
首先会根据BeanName
去获取RootBeanDefinition
,获取到RootBeanDefinition
之后判断当前需要初始化的Bean
是否是FactoryBean>
,如果是FactoryBean>
并且需要提前初始化则会调用getBean()
方法进行实例化。否则直接调用getBean()
方法对BeanName
所指代的Bean
进行初始化。
MergedBeanDefintion
MeregedBeanDefintion
并不是一个官方词汇,这是Spring
中对于RootBeanDefinition
的变量命名。主要用来表示合并的Bean定义信息。Spring
中缩写为mbd
。
对于一个BeanDefinition
来说,可能存在以下几种情况:
BeanDefinition
可能存在父定义信息,这种情况下Spring
通常会使用父定义信息的参数构建一个RootBeanDefinition
,然后再使用该BeanDefinition
的参数对其进行覆盖。RootBeanDefintion
:一个BeanDefinition
不存在父定义,并且该BeanDefinition
的类型是RootBeanDefinition
,这种情况下Spring
会直接返回该RootBeanDefinition
的克隆。RootBeanDefintion
:一个BeanDefinition
不存在父定义且不为RootBeanDefinition
,这种情况下Spring
会使用该BeanDefinition
的参数构建一个RootBeanDefinition
返回。可以看出Spring
最终处理的BeanDefinition
都是RootBeanDefinition
。
通常Spring
为BeanFactory
解析对Bean
的配置时,都是将获取到的BeanDefinition
包装成GenericBeanDefinition
或ScannedGenericBeanDefinition
通用的Bean
定义信息。但是Spring
在对Bean
进行初始化时处理的都是RootBeanDefinition
。所以Spring
会在这里统一将BeanDefinition
转换成RootBeanDefinition
。
我们在应用程序中定义的Bean
一般都是第三种情况。如果使用XML
配置文件来声明Bean
,那么被声明的Bean
将会被封装成GenericBeanDefinition
。如果使用注解的方式来声明Bean
,那么被声明的Bean
将会被封装成ScannedGenericBeanDefinition
。
GitHub源码地址:https://github.com/kapbc/kapcb-spring-source/tree/master/Spring-Framework-v5.3.13
备注:此文为笔者学习
Spring
源码的笔记,鉴于本人技术有限,文中难免出现一些错误,感谢大家批评指正。