spring源码:bean加载之创建bean-提前曝光bean的Object-Factory

一、介绍

  提前曝光bean的Object-Factory是spring为了解决bean循环依赖的一种方法。

  • 什么是循环依赖
    在这里插入图片描述
    spring加载一个bean需要两个步骤:1.创建bean;2.给这个bean填充属性
    如上图,加载类A的步骤为:
  1. 先创建A,然后给A填充属性的时候,发现A依赖一个类B属性,所以去加载B;
  2. 创建B,然后给B填充属性的时候,发现B依赖一个类C属性,所以去加载C;
  3. 创建C,然后给C填充属性的时候,发现C依赖一个A属性,所以又会去加载A。。。

这样就形成了没完没了的循环依赖!

  • 解决办法:提前曝光bean的Object-Factory
    当创建一个bean之后,不等执行填充属性这个步骤,就把该bean实例存入到一个Map中(DefaultSingletonBeanRegistry#singletonFactories),创建一个bean时,就先去这个Map中查找有没有对应的bean实例已经创建了,如果有的话直接就属性填充完成了。

spring只解决了单例中,setter注入引起的循环依赖问题。原型bean和构造器注入引起的循环依赖问题不能解决。

二、bean加载流程

  1. 获取用户传入name对应的beanName
  2. 尝试从缓存中获取bean实例
  3. 缓存中不存在,加载bean实例
    3.1. 检查循环依赖
    3.2 处理parentBeanFactory
    3.3 处理依赖的bean(dependsOn)
    3.4 三种bean实例的创建
     3.4.1 单例bean的创建
      3.4.1.1 获取单例bean,getSingleton()方法
      3.4.1.2 准备创建bean,createBean()方法
      3.4.1.3 创建bean,doCreateBean()方法
       3.4.1.3.1 创建BeanWrapper
       3.4.1.3.2 记录bean的Object-Factory(本章解析
     3.4.2 原型bean的创建
     3.4.3 根据scope策略创建bean
  4. 从bean实例中获取真正的对象
  5. 转换对象类型
  6. 返回对象实例

三、相关类及方法

  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean:创建bean流程
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory:提前曝光bean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference:获取提前依赖的bean(循环依赖的情况使用)

四、源码分析

1. 提前曝光单例bean

		// 单例&&允许循环引用&&该bean在创建中
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		// 需要提早曝光单例
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 把创建实例的ObjectFactory加入单例工厂
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				// 创建bean实例的ObjectFactory加入到singletonFactories
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}
  • 创建中的beanName
    保存在DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation中。执行保存bean状态的代码逻辑在DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>),创建bean之前会把该bean保存到singletonsCurrentlyInCreation,创建完成之后从singletonsCurrentlyInCreation移除。
  • 提前曝光的bean
    该bean保存在DefaultSingletonBeanRegistry#singletonFactories,用来解决循环依赖。

2. 获取提前曝光的bean

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					// 应用SmartInstantiationAwareBeanPostProcessor
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

这个方法的入参bean,其实已经是创建好的bean实例了。经过这个方法是为了给用户自定义的SmartInstantiationAwareBeanPostProcessor一个机会,来根据自己的需要制定一个需要的bean。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章