spring系列-Spring Bean创建过程和循环依赖原理分析

一、整体流程分析

在这里插入图片描述

图中是我整理的相关Bean创建流程,主要可以分为三层:

  1. AbstractBeanFactory定义了Bean创建的主流程
  2. DefaultSingletonBeanRegistry定了Singleton Bean注册的主流程
  3. AbstractAutowireCapableBeanFactory类提供了Bean 实例创建的具体方法.

下面将从以下几个方面来总结Bean创建的整个流程:

  1. Bean创建整体流程分析
  2. Bean创建具体内容分析-实例化、初始化、Bean创建流程中的扩展接口
  3. 循环依赖解决的原理

二、Bean创建整体流程说明

通过上面图的流程分析,我们看到Bean的创建过程,大致分为三个层次,下面分别看下者三个层次做了什么事情.

2.1.AbstractBeanFactory.doGetBean

AbstractBeanFactory的继承体系

在这里插入图片描述

AbstractBeanFactory主要作用如下:

  1. 实现Beanfactory接口:提供获取Bean的接口,触发Bean的创建工作
  2. 继承FactoryBeanRegistrySupport类,该类提供了SingletonBeanRegistry功能,即单例Bean的注册功能(Bean创建)

这就不难理解为什么要在,DefaultListableBeanFactory.preInstantiateSingletons()方法中触发用户定义的所有Bean的初始化了,因为DefaultListableBeanFactory持有了当前容器中用户定义的Bean的BeanDefinition信息和所有的beanName信息,那么只需要遍历,调用AbstractBeanFactory.getBean(beanName)就可以完成所有bean的创建了

AbstractBeanFactory类中Bean创建流程主要在doGetBean方法中,该方法主要逻辑如下:

	private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  //1转换Bean名称
  final String beanName = transformedBeanName(name);

  Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
		    //2.1检查是否循环依赖,如果是,先获取依赖Bean的引用
      ....
		}else{
      //2.2正常创建
      if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 如果当前BeanFactory设置了父BeanFactory,交由父BeanFactory创建Bean
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
			  //..父BeanFactory创建bean
			}
       //将beanName放到alreadyCreated集合,在该层中标记beanName对应的Bean正在创建 ,这个缓存和循环依赖没有关系
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
      //获取当前beanName对应的BeanDefinition类
      final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
      String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
         //处理@DependsOn 依赖的bean,也是根据beanName加载对应bean的流程
      }
      //singleton类型bean创建
      if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}else if (mbd.isPrototype()) {
         //prototype类型Bean创建
        }else{
         //scope 类型Bean创建
        }

      
          // 是否需要根据给定的类型转化bean
        if (requiredType != null && !requiredType.isInstance(bean)) {
          try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
              throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
          }
          catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
              logger.debug("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
          }
        }
        return (T) bean;
     
    }
  
}

2.1.1.alreadyCreated集合的作用:

用于存放当前已经开始创建Bean的beanname,因为在多线程的情况下,如果要是在创建Bean的过程中,有可能有的线程还在通过DefaultListableBeanFactory往容器内注册Bean的BeanDefinition,而Bean的初始化开始时,是在DefaultListableBeanFactory通过遍历beanDefinitionNames所有beanName进行注册Bean的,所以有可能会造成iterator不安全.

伪代码如下:

//容器ApplicationContext触发Bean的初始化流程
Map<String, BeanDefinition> beanDefinitionMap = new HashMap();
List<String> beanDefinitionNames = new ArrayList();
//加载了 BeanDefinition
....
  
preInstantiateSingletons(){
  //开始初始化
for(String beanName : this.beanDefinitionNames){
   getBean(beanName)
}
}  

//这时如果并发的再注册Bean,那么beanDefinitionNames,动态添加将是不安全的.

2.1.2.Singleton类型Bean创建入口

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

在singleton类型分之,主要有这两个函数调用:

  1. getSingleton: 执行singleton实例的创建流程
  2. getObjectForBeanInstance:
    1. 如果getSingleton返回不是FactoryBean则,正常返回
    2. 如果是FactoryBean,则调用FactoryBean.getObject()方法

接下来看getSingleton方法.

2.2.DefaultSingletonBeanRegistry.getSingleton

以下是getSingleton方法代码:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

getSingleton方法内容比较简单,主要分为以下内容:

  1. 查看当前单例Bean集合singletonObjects中是否存在beanName对应的bean,如果存在直接返回
  2. 执行传入的ObjectFactory.getObject()方法,得到单例Bean实例
  3. 将单例Bean实例假加入到singletonObjects

其中ObjectFactory.getObject()方法就是AbstractBeanFactory中的createBean方法,是创建Bean实例的具体方法.

另外,DefaultSingletonBeanRegistry中还维护了spring 中bean创建过程中使用到的三个缓存集合:

  1. singletonObjects: 存放最终Bean的单例集合
  2. singletonFactories: 临时存放Bean创建过程中的FactoryBean
  3. earlySingletonObjects: 存放循环依赖的Bean引用

后面会讲到这三个集合是如何配合使用的.

2.3.AbstractAutowireCapableBeanFactory.createBean

再贴一次上面的流程图:

在这里插入图片描述

真正创建Bean时,经过以下几步:

  1. 是否存在InstantiationAwareBeanPostProcessor类型的BeanProcessor,在调用其postProcessBeforeInstantiation方法时,创建了一个自定义的Bean
    1. 如果是结束Bean创建流程,使用该Bean
    2. 否则,继续执行Bean创建流程
  2. 获得Bean对应Class的实例
  3. 处理循环依赖,暴露引用
  4. 属性填充(依赖注入)
  5. 执行初始化相关接口
  6. 注册Bean为DisposableBean

下面对每一步进行分析.

三、Bean创建具体流程

3.1.InstantiationAwareBeanPostProcessor

我们看下该类的注释:

 This interface is a special purpose interface, mainly for
 * internal use within the framework. It is recommended to implement the plain
 * {@link BeanPostProcessor} interface as far as possible, or to derive from
 * {@link InstantiationAwareBeanPostProcessorAdapter} in order to be shielded
 * from extensions to this interface.

InstantiationAwareBeanPostProcessor这个接口是有特殊用途的,主要在spring框架内部使用.

一般推荐推荐使用BeanPostProcessor或InstantiationAwareBeanPostProcessorAdapter来实现增强bean的功能.

接口定义代码:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true;
	}

	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}

}

方法说明:

  1. postProcessBeforeInstantiation: 在Bean实例化之前调用,默认返回null
    1. .如果返回不为null,那么Bean创建过程就会提前结束,并会接着调用所有的BeanPostProcessor.postProcessAfterInitialization
    2. 该方法不会作用到一个工厂方法
  2. postProcessAfterInstantiation实例化后调用,在执行属性注入是,首先被调用,这是属性还未注入.
    1. 该方法用于特殊属性注入.
    2. 如果返回false,当前Bean将不会执行后续的属性注入.
  3. postProcessPropertyValues: 当前属性注入的属性值集合
    1. 可以对特殊的属性进行修改,默认返回原有的属性集合
    2. 如果返回null,那么将跳过后续的属性注入逻辑.

特别注意:

spring中AOP实现AspectJAwareAdvisorAutoProxyCreator,就是该接口的子类.

3.2.Bean对应Class实例化方式

Bean对应Class实例化方式有以下几种:

  1. 使用Supplier返回一个实例
  2. 使用指定FactoryBean.工厂方法获取
  3. 使用有参构造函数或无参构造函数获取实例, 默认是无参构造函数

3.3.属性填充

在springBean创建过程中,对属性依赖注入,支持三种情况:

  1. AUTOWIRE_BY_NAME: 通过bean名称注入
  2. AUTOWIRE_BY_TYPE: 通过Bean类型注入,默认的注入方式
  3. AUTOWIRE_CONSTRUCTOR: 通过构造函数注入,会对构造器参数,进行自动bean注入,进而赋值到属性上.

3.4.初始化接口

Bean初始化接口主要分为三类:

  1. *Aware接口
  2. BeanPostProcessor接口
    1. postProcessBeforeInitialization
    2. postProcessAfterInitialization
  3. InitializingBean接口

执行顺序:

Aware接口->BeanPostProcessor.postProcessBeforeInitialization->InitializingBean接口->BeanPostProcessor.postProcessAfterInitialization

为什么是这个顺序?

  1. Aware接口一般是注入一些Spring维护的一些信息:如BeanName,BeanFactory等,这些一般是在类中以属性体现,可以算是Bean属性的一部分,只不过是通过Aware的方式注入.
  2. InitializingBean接口是开发者定义的一些逻辑,是在所有的属性值已经赋值完成时执行.
  3. BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法,可以在InitializingBean前后,对bean进行包装,如生成代理等.
    1. postProcessAfterInitialization还会在InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation返回不为null时执行,即提前终结bean创建时,也会被调用.

3.4.1.Aware接口

Bean在创建过程中会执行,以下三个Aware接口的调用:

  1. BeanNameAware : 设置BeanName
  2. BeanClassLoaderAware: 设置当前Beanfactory的ClassLoader
  3. BeanFactoryAware: 设置当前的BeanFactory

3.5.DisposableBean

在Bean创建的过程的最后阶段,Spring会把Bean包装成DisposableBeanAdapter,注册到DefaultSingletonBeanRegistry中的Map<String, Object> disposableBeans 集合中,用于在Spring的ApplicationContext关闭时,调用对应的destroy方法,执行Bean的销毁工作.

DisposableBeanAdapter.destroy方法代码如下:

@Override
	public void destroy() {
		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
				processor.postProcessBeforeDestruction(this.bean, this.beanName);
			}
		}

		if (this.invokeDisposableBean) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((DisposableBean) this.bean).destroy();
						return null;
					}, this.acc);
				}
				else {
					((DisposableBean) this.bean).destroy();
				}
			}
			catch (Throwable ex) {
				String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
				if (logger.isDebugEnabled()) {
					logger.warn(msg, ex);
				}
				else {
					logger.warn(msg + ": " + ex);
				}
			}
		}

		if (this.destroyMethod != null) {
			invokeCustomDestroyMethod(this.destroyMethod);
		}
		else if (this.destroyMethodName != null) {
			Method methodToCall = determineDestroyMethod(this.destroyMethodName);
			if (methodToCall != null) {
				invokeCustomDestroyMethod(methodToCall);
			}
		}
	}

它会调用bean上定义的destroy-method指定的方法.

四、FactoryBean原理

以具体例子来说明FactoryBean的原理:

@Component
public class FactoryBeanService implements FactoryBean<AddressService> {

    @Override
    public AddressService getObject() throws Exception {
        System.out.println("AddressService");
        return new AddressServiceImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return AddressService.class;
    }
}

public interface AddressService {
}


public class AddressServiceImpl implements AddressService {
}

当在执行Bean创建流程时,参考第一章部分,会首先创建一个FactoryBeanService对应的Bean,即:

singletonObjects集合中存在:
factoryBeanService-> factoryBeanService 对应的Bean

这是如果通过context.getBean(AddressService.class)或者通过@Autowire在别的Bean中注入AddressService时就会再次走Bean创建流程,创建AddressService对应的Bean,流程如下:

  1. 首先会遍历所有的当前容器中所有的beanDefinitionNames,查找有没有该类型对应的Bean,
    1. 因为当前Bean还不存在,并且它会有FactoryBean产生,
    2. 所以遍历到对应的FactoryBean即FactoryBeanService时,会调用FactoryBean的getObjectType()方法,发现匹配,返回对应FactoryBean的beanName.
  2. 根据返回的FactoryBean的beanName执行AbstractBeanFactory.doGetBean方法
    1. 因为当前已经存在FactoryBeanService对应的Bean,那么在Object sharedInstance = getSingleton(beanName);将不会返回null
    2. 执行getObjectForBeanInstance
      1. 调用FactoryBeanService的getObject()方法
      2. 将当前FactoryBeanService对应的beanName即factoryBeanService添加到factoryBeanObjectCache缓存中

总结:

  1. 先创建FactoryBean对应的Bean并放到singletonObjects集合
  2. 创建对应类型的Bean时,调用FactoryBean.getObject()方法
  3. 将当前FactoryBean对应的beanName和getObject返回的Bean的实例加入FactoryBean的缓存factoryBeanObjectCache中,防止反复调用getObject

五、循环依赖解决的原理

在这里插入图片描述

我们将通过上图来说明以下Spring解决循环依赖的原理.

首先,再次说下Spring三级缓存对应到代码中是,DefaultSingletonBeanRegistry中的:

  1. Map<String, Object> singletonObjects : 最终所有生成的单例Bean都会放到这里,可以叫做单例池,即上图中的S-Map
  2. Map<String, ObjectFactory<?>> singletonFactories: 提前暴露的工厂集合,即上图的SF-Map
  3. Map<String, Object> earlySingletonObjects : 需要提前实例化的单例集合,这个提前的含义后面会说.

下面我们通过上图和代码一起结合说明.

首先:循环依赖的代码在AbstractAutowireCapableBeanFactory.doCreateBean中.

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
     ...
		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		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");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
		  ...
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

在每个一个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");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

这块代码的含义的是,将一个ObjectFactory类型放到singletonFactories,即上面的SF-Map.

5.1.无循环依赖时简单singleton Bean创建

那么首先分析无循环依赖时,如何创建Bean A,步骤如下

第一步:

将Bean A对应的ObjectFactory对象放到singletonFactories,

第二步:

正常实例化Bean 对应的Class,执行属性注入、初始化接口调用

第三步:

当Bean创建完成,在第一章的总图中,第二张图,即DefaultSingletonBeanRegistry.getSingleton方法中,

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

​ addSingleton(beanName, singletonObject);这步,我们看下代码:

	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

我们看到,将该bean的对应的beanName从singletonFactories移除,即刚才我们加入的ObjectFactory对象被移除,没有使用到,并且还会移除earlySingletonObjects中对应的内容,虽然也没有添加.

然后将beanName->bean 加入到singletonObjects,即完成当前bean的创建.

总结:

  1. 创建bean前首先把bean对应的ObjectFactory加入singletonFactories,
  2. bean创建完成,从singletonFactories移除,并加入到singletonObjects

5.1.有循环依赖时简单singleton Bean创建

假设现在如图中所示,A依赖B,B依赖A.

那么按照我们上面的流程,假如先创建A,则

  1. A对应的ObjectFactory先加入singletonFactories
  2. 继续进行创建A
  3. 属性注入(populateBean)时,发现需要B
    1. 创建B
    2. B对应的ObjectFactory先加入singletonFactories
    3. 继续创建B
    4. 属性注入(populateBean)时,发现需要A,这时就关键了

那么怎么找A呢?

Spring默认是按类型注入,这里假设我们没有做任何特别设置,那么也是按类型注入,那么将会进行如下步骤:

  1. 根据A的类型,找到容器中对应类型的BeanDefinition,并获取beanName
  2. 调用DefaultSingletonBeanRegistry.getSingleton(beanName)方法,这里就是循环依赖解决的关键

我们看下getSingleton这个方法:

public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
	
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

这时调用的是

getSingleton(String beanName),也就是说调用getSingleton(String beanName, boolean allowEarlyReference)时,allowEarlyReference为true.

我们看下这个方法做了什么:

  1. 先从singletonObjects中找,因为这时A还未创建完成,所以这里返回null
  2. 接着从earlySingletonObjects找,因为这里我们也没有放,所以也是null
  3. 然后allowEarlyReference为true,这时我们就能从singletonFactories中找了,
  4. singletonFactories,我们在doCreatebean时已经放入了,时一个ObjectFactory
  5. 这时调用ObjectFactory.getObject(),返回一个对象
  6. 把该对象放入到earlySingletonObjects,并且从singletonFactories删除

从这里我们明白了earlySingletonObjects这个缓存的含义:

就是某一个Bean 例如A创建的过程中,由于循环依赖的存在提前需要执行完成一些操作,并且把操作后的对象 加入 Proxy A放到这里,使得当最开始的A属性注入完,可以继续执行后续的操作.

看下ObjectFactory.getObject()操作做了什么:

() -> getEarlyBeanReference(beanName, mbd, bean)

这是我们放入的ObjectFactory, getEarlyBeanReference 逻辑如下:

	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 ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		return exposedObject;
	}

//SmartInstantiationAwareBeanPostProcessor
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		return bean;
	}


SmartInstantiationAwareBeanPostProcessor类的getEarlyBeanReference默认是返回传入的Bean.但是,如果SmartInstantiationAwareBeanPostProcessor

开启了AOP功能,并且当前Bean需要AOP功能,那么就会在AbstractAutoProxyCreator类中,对当前Bean进行代理包装,并将当前beanName加入earlyProxyReferences集合,返回代理类.

	private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	
@Override
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			this.earlyProxyReferences.add(cacheKey);
		}
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

这时earlySingletonObjects中就会存在 beanName a->ProxyA

那么在原先A属性属性注入完,会怎么处理?

在初始化步骤,spring会执行BeanPostProcessor的postProcessAfterInitialization.时,一定会执行到AbstractAutoProxyCreator的postProcessAfterInitialization方法

	private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

而earlyProxyReferences就保存了之前在getEarlyBeanReference生成的ProxyA对应的beanName,那么就会直接放回当前bean.

这就是earlySingletonObjects存在的价值,为了解决含有代理逻辑的循环依赖解决方案.

下面用一个小图总结一下:

在这里插入图片描述

  1. 首先为A创建ObjectFactory 对象放入singletonFactories,所有正常单例bean都有这一步

  2. 如果存在循环依赖,则会被调用ObjectFactory.getObject()

    1. 如果存在代理逻辑,
      1. 那么生成代理,并将代理类维护到 一个代理类缓存里面,
      2. 返回代理类,加入到earlySingletonObjects
    2. 原有流程继续执行属性注入,然后在初始化接口调用时
      1. 如果存在代理逻辑,则
        1. 一定要调用到代理类创建逻辑,通过代理类缓存获取之前生成的代理,然后返回
  3. 当创建Bean流程完成后,

    1. 将bean加入到singletonObjects单例池集合
    2. 从singletonFactories删除beanName和对应的ObjectFactory
    3. 从earlySingletonObjects删除beanName和对应的代理类
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿老徐

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值