spring5.0 源码解析(day08)finishBeanFactoryInitialization
- spring 在初始化所有剩余的单例bean做了哪些准备
- 为此上下文初始化 类型转换器
- 检查上下文中是否存在类型转换器
- 优先初始化的bean
- 设置参数
- 实例化所有剩余的(非延迟初始化)单例
- preInstantiateSingletons
- getBean
- doGetBean
- createBean
- doCreateBean
这个方法用于实例化所有剩余的(非延迟初始化)单例,我愿称之为 spring源码中最难的一部分,建议新手先去看一本书叫做 《spring揭秘》 他是从设计的角度讲解spring核心思想,而不是 上来就直接搞源码。
spring 在初始化所有剩余的单例bean做了哪些准备
为此上下文初始化 类型转换器
ConversionService 是一个 用于类型转换的服务接口
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));
}
检查上下文中是否存在类型转换器
// 检查上下文中是否存在类型转换器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
优先初始化的bean
// 尽早初始化 LoadTimeWeaverAware bean 以允许尽早注册它们的转换器.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
设置参数
// 禁止使用临时类加载器进行类型匹配.
beanFactory.setTempClassLoader(null);
// 允许缓存所有的bean的定义数据.
beanFactory.freezeConfiguration();
实例化所有剩余的(非延迟初始化)单例
beanFactory.preInstantiateSingletons();
preInstantiateSingletons
- 先获取所有的beanName
// 获取所有bean的名字
// beanDefinitionNames 按注册顺序排列的一个 beanDefinition集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
- 循环 实例化非懒加载的 bean
- getMergedLocalBeanDefinition
初始化时,使用的统一视图是RootBeanDefinition,这里可以看到spring对于具有继承关系的Bean的处理方式——首先初始化父BeanDefinition,
接着将子BeanDefinition的内容覆盖父BeanDefinition的内容 - isFactoryBean(beanName)
如果 bean 是 factoryBean,先获取 &+ beanName 也就是工厂bean
之后 根据 isEagerInit 判断是否要初始化 factoryBean要生产的bean - ! isFactoryBean(beanName)
直接执行getBean
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// 获取系统范围的安全管理器 // 实现SmartFactoryBean可以指示它们是否总是返回独立实例
// 如果工厂类继承了SmartFactoryBean,并且isEagerInit()返回True,则在初始化工厂类之后,立刻初始化产品类
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);
}
- 在初始化Bean之后,若Bean继承了SmartInitializingSingleton,则调用相应的生命周期回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
// SmartInitializingSingleton 单例预实例化阶段结束时触发的回调接口
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
// 类型转换
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
getBean
getBean 内部调用 doGetBean
return doGetBean(name, null, null, false);
doGetBean
- 获取规范名称
返回 bean 名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称。
tring beanName = transformedBeanName(name);
- 检查缓存中是否有该bean
Object sharedInstance = getSingleton(beanName);
通过三级缓存查找解决了 单例非懒加载的bean的循环依赖问题
// 一级缓存 进行查找
Object singletonObject = this.singletonObjects.get(beanName);
// 判断是否在创建过程中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 二级缓存中获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 二级缓存没有获取到 允许早期引用
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 一级缓存查找
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 二级缓存查找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 三级缓存 获取到 objectFactory 的 getEarlyBeanReference 方法
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 这里的getObject 实际上调用的是 getEarlyBeanReference 取到的是循环依赖的半成品对象
singletonObject = singletonFactory.getObject();
// 二级缓存 放入 bean
this.earlySingletonObjects.put(beanName, singletonObject);
// 三级缓存清除数据
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
- 检查缓存中是否有该bean
- 缓存中找到该bean
使用 getObjectForBeanInstance 完成的是FactoryBean的相关处理,已取得FactoryBean的生产结果。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); - 缓存中没有找到该bean
1.对Ioc 容器中的 BeanDefition 是否存在进行检查,检查是否能在当前的BeanFactory中获取到Bean,如果在当前工厂中取不到,则到双亲BeanFactory中去取,如果双亲中娶不到,那就顺着双亲beanFactory链一直向上寻找
2. 判断调用getBean()是否仅仅是为了类型检查获取bean,如果是为了创建bean,则先清除掉合并BeanDefinition的标记(使之重新合并)
3. // 获取 合并之后的 bean定义
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
4. 获取该bean所有依赖的 bean
5. 创建bean实例. (这里区分了是否为 Singleton , Prototype) 这里使用了函数式编程
if (mbd.isSingleton()) {
// 函数式编程 ObjectFactory<?> singletonFactory 。getObject() 方法
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean对象
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
- 最后 对创建的bean 进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的bean
adaptBeanInstance(name, beanInstance, requiredType);
createBean
创建bean实例
- 解析beanName对应的Bean的类型
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),
则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,该拷贝副本取代mdb用于后续的操作 - 如果bean配置了 PostProcessor ,那么返回一个proxy
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
InstantiationAwareBeanPostProcessor 他是bean实例化的处理器 通常用于抑制特定目标bean的默认实例化 - 调用 doCreateBean(beanName, mbdToUse, args) 创建bean
doCreateBean
- 声明一个 BeanWrapper 用来持有创建出来的bean 对象, (其实也是一个策略模式,因为他包含了反射相关算法)
- 如果是单例的,先把缓存中同名的bean清除
- createBeanInstance() 创建bean实例
- 获取 bean对象
- MergedBeanDefinitionPostProcessor 处理 ,在bean初始化的时候来提前收集到这些标记了@Value的字段或者方法
- 放入三级缓存中
- 属性填充
- 执行 initializeBean() 初始化bean
- 检查是否是一个完整的对象
- 注册销毁方法