spring5.0 源码解析 finishBeanFactoryInitialization 总览(08)

这个方法用于实例化所有剩余的(非延迟初始化)单例,我愿称之为 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

  1. 先获取所有的beanName
// 获取所有bean的名字
// beanDefinitionNames 按注册顺序排列的一个 beanDefinition集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  1. 循环 实例化非懒加载的 bean
    1. getMergedLocalBeanDefinition
      初始化时,使用的统一视图是RootBeanDefinition,这里可以看到spring对于具有继承关系的Bean的处理方式——首先初始化父BeanDefinition,
      接着将子BeanDefinition的内容覆盖父BeanDefinition的内容
    2. isFactoryBean(beanName)
      如果 bean 是 factoryBean,先获取 &+ beanName 也就是工厂bean
      之后 根据 isEagerInit 判断是否要初始化 factoryBean要生产的bean
    3. ! 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);
						}
  1. 在初始化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

  1. 获取规范名称
    返回 bean 名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称。
	tring beanName = transformedBeanName(name);
  1. 检查缓存中是否有该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);
							}
						}
					}
				}
			}
		}
  1. 检查缓存中是否有该bean
    1. 缓存中找到该bean
      使用 getObjectForBeanInstance 完成的是FactoryBean的相关处理,已取得FactoryBean的生产结果。
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);

    2. 缓存中没有找到该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);
				}
  1. 最后 对创建的bean 进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的bean
    adaptBeanInstance(name, beanInstance, requiredType);

createBean

创建bean实例

  1. 解析beanName对应的Bean的类型
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),
    则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,该拷贝副本取代mdb用于后续的操作
  2. 如果bean配置了 PostProcessor ,那么返回一个proxy
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    InstantiationAwareBeanPostProcessor 他是bean实例化的处理器 通常用于抑制特定目标bean的默认实例化
  3. 调用 doCreateBean(beanName, mbdToUse, args) 创建bean

doCreateBean

  1. 声明一个 BeanWrapper 用来持有创建出来的bean 对象, (其实也是一个策略模式,因为他包含了反射相关算法)
  2. 如果是单例的,先把缓存中同名的bean清除
  3. createBeanInstance() 创建bean实例
  4. 获取 bean对象
  5. MergedBeanDefinitionPostProcessor 处理 ,在bean初始化的时候来提前收集到这些标记了@Value的字段或者方法
  6. 放入三级缓存中
  7. 属性填充
  8. 执行 initializeBean() 初始化bean
  9. 检查是否是一个完整的对象
  10. 注册销毁方法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1999

每人一点点,明天会更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值