Spring源码解析---从原始状态bean创建FactoryBean

由于Spring工厂创建bean的过程过于复杂,故分解为多篇文章,此篇文章分析FactoryBean的创建,以及单例FactoryBean是如何处理循环依赖的,对循环依赖作初步了解。

首先看bean工厂的继承图,首先得先熟悉下涉及到创建FactoryBean的几个类的作用,不至于后续在debug过程中“迷路”了

bean工厂uml图

bean工厂uml图
AliasRegistry接口:用于管理别名的通用接口
SimpleAliasRegistry类:AliasRegistry的简单实现类,其主要属性如下:

public class SimpleAliasRegistry implements AliasRegistry {
	/*有了该属性就可通过bean的别名找到bean的最终名称:如beanA的别名是beanB,而beanB的别名是beanC;则此集合会这么存储该结果:
	* beanC->beanB;beanB-BeanA;	即key为别名,value为最终名称;只要通过数次循环就可通过别名找到最终名称
	*/
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

FactoryBeanRegistrySupport类:用于管理FactoryBean实例,其主要属性如下:

	//key为beanName,value为FactoryBean通过getObject方法创建的实例;
	//如果是单例的bean,则会加入该缓存
	private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

DefaultSingletonBeanRegistry类:这个类用于管理单例bean。这个类较为重要,处理循环依赖的相关属性都在此类;但针对于FactoryBean而言,没有使用到三级缓存;主要看singletonsCurrentlyInCreation 属性就可。其主要属性如下:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	//一级缓存,key为beanName,value为创建完成的bean实例;在单例bean创建完成后都会将其加入该缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 三级缓存,key为beanName,value为ObjectFactory对象,调用该对象的getObject方法就会返回还未创建完成的bean
	  * 那么既然bean还未创建完成,调用getObject方法返回的是什么?返回的还未创建完成的bean处于一种什么状态?
	  * 其实就是在bean使用默认的无参构造器实例化好了对象,但是其属性还未完成setter注入,这个状态就叫bean还未创建完成。对于Spring
	  * 工厂而言,只有在bean实例化完成,并且所有配置的属性已注入,并且经过所有注册的后处理器(当然可能没有注册后处理器,那就不需要处理)
	  * 处理后,这个bean才算创建完成。
	  */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** 二级缓存,key为beanName,value为使用无参构造器实例化的bean实例 */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	/** 正在创建中的beanName集合。该属性是为了解决循环依赖。 在bean实例化完成后,初始化阶段或者后处理器阶段,都会使用到该属性*/
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** 在该集合中的beanName不用检查循环依赖 */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** Collection of suppressed Exceptions, available for associating related causes. */
	@Nullable
	private Set<Exception> suppressedExceptions;

	/** Flag that indicates whether we're currently within destroySingletons. */
	private boolean singletonsCurrentlyInDestruction = false;

	/** Disposable bean instances: bean name to disposable instance. */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

	/** 用于缓存所有内嵌bean。内嵌bean:在<constructor-arg>或者<property>标签下的<bean>标签,作为函数构造器或者set方法某个参数的值 */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	/** key为被依赖的bean,value为依赖key的bean */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	/** 这个和上面相反,key为依赖value的bean,value为被key依赖的bean */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

在此首先介绍下循环依赖

循环依赖分为2种,构造器注入循环依赖以及setter循环依赖。Spring无法解决构造器循环依赖,只解决了setter注入循环依赖。

Spring如何解决setter循环依赖?

例如如下代码:

public class BeanA {
    public BeanB beanB;
    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }
}

public class BeanB {
    public BeanC beanC;
    public void setBeanC(BeanC beanC) {
        this.beanC = beanC;
    }
}

public class BeanC {
    public BeanA beanA;
    public void setBeanA(BeanA beanA) {
        this.beanA = beanA;
    }
}
    <bean id="beanA" class="com.example.demo.循环依赖.BeanA">
        <property name="beanB" ref="beanB" />
    </bean>
    <bean id="beanB" class="com.example.demo.循环依赖.BeanB">
        <property name="beanC" ref="beanC" />
    </bean>
    <bean id="beanC" class="com.example.demo.循环依赖.BeanC">
        <property name="beanA" ref="beanA" />
    </bean>

当容器调用getBean(“beanA”)时,Spring会进行如下操作:
1、使用BeanA的无参构造器实例化beanA,并将beanA放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanA)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanB,此时beanB还未创建;
2、使用BeanB的无参构造器实例化beaB,并将beanB放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanB)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanC,此时beanC还未创建;
3、使用BeanC的无参构造器实例化beanC,并将beanA放进“正在创建的bean中”(也就是singletonsCurrentlyInCreation 属性),再创建一个ObjectFactory对象(该对象可以使用getObject方法返回beanC)放入三级缓存(也就是singletonFactories 属性)。然后进行setter注入beanA,此时beanA已经完成实例化;故从三级缓存中获取其ObjectFactory对象,调用getObject方法获取实例化好的beanA(此时beanA实际上并未创建完成);
4、然后再注入beanB,BeanC。

AbstractBeanFactory # doGetBean

1、规范传入的name
2、从缓存中获取bean(该bean是原始状态的)
3、对获取的bean进行处理

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		/* 总结这个方法:首先取消工厂前缀(&,有多个就取消多少个);再将其从bean别名转换成原始bean名称
		* 
		* 其中取消多个工厂前缀很简单,就是循环多次,若开头是&就直接截取字符串;
		* 那么规范名称呢?SimpleAliasRegistry中有别名缓存,即this.aliasMap(ConcurrentHashMap<String, String>),该属性表示从别名映射到规范
		* 名称。也就是可通过该集合找到最终的原始名称
		*/
		String beanName = transformedBeanName(name);
		Object bean;

		/* 从缓存中获取原始状态的单例bean(原始状态即可能是工厂bean或者FactoryBean,而非真正需要的 bean本身)
		* 
		* 总结这个方法:该方法使用三级缓存,若beanName不在一级缓存并且该bean在创建中,就调用二级缓存;若二级缓存仍然找不到并且该bean允许早期引用,才调用三级缓存。
		*/ 
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			//对bean进行检测,获取真正需要的bean
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		// Check if required type matches the type of the actual bean instance.
		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.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;	
		}

DefaultSingletonBeanRegistry # getSingleton:设置标识

	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		//参数true设置标识允许早期依赖
		return getSingleton(beanName, true);
	}

DefaultSingletonBeanRegistry # getSingleton:双重检测锁单例

this.singletonObjects:保存BeanName和创建bean实例之间的关系
this.earlySingletonObjects:保存BeanName和创建bean实例之间的关系,目的是检测循环引用
this.singletonFactories:保存BeanName和创建Bean的工厂之间的关系
this.singletonsCurrentlyInCreation:?

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

getObjectForBeanInstance:处理FactoryBean

1、检验传入的name是否以&开头 ;并且 beanInstance(从缓存获取的原始状态bean)不是FactoryBean则抛出异常;(也就是用户需要创建name对象的FactoryBean对象,但缓存中注册在该名字下的beanInstance却不是FactoryBean,所以报错)
2、检验beanInstance是否是普通bean,若是则直接返回
3、判断缓存中是否存在该FactoryBean
- 不存在则读取其BeanDefinition,若存在parent则合并父BeanDefinition,最后生成RootBeanDefinition对象
- 存在则返回
4、通过FactoryBean实例创建bean实例

this.factoryBeanObjectCache:FactoryBeans 创建的单例对象的缓存:FactoryBean 名称-》对象。

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		//若要获取的就是工厂bean,则直接返回;若用户要获取的是工厂bean,但beanInstance不是FactoryBean,则抛出异常
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {	mbd.isFactoryBean = true;	}
			return beanInstance;
		}
		
		//经过上面条件的过滤,代码来到此处说明用户需要获取的bean是FactoryBean创建的普通bean或者是普通bean
		//而beanInstance可能是FactoryBean或者普通bean
		
		//如果不是FactoryBean,则不用处理,因为其本身就是实际需要的bean,直接返回
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
		
		//对FactoryBean开始处理
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			//尝试从factoryBeanObjectCache缓存中获取,该方法位于父类FactoryBeanRegistrySupport中,该父类用于管理FactoryBean
			object = getCachedObjectForFactoryBean(beanName);
		}
		//若缓存中不存在,则直接读取beanName对应的BeanDefinition,然后进行实例化
		if (object == null) {
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			if (mbd == null && containsBeanDefinition(beanName)) {
				//合并BeanDefinition,并生成RootBeanDefinition返回
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getMergedLocalBeanDefinition:合并标签的缓存

为何要合并parent的BeanDefinition?

因为在将Xml文件解析成BeanDefinition时,对于有的bean标签属性继承于parent,不合并parent属性则其bean标签属性不完善。

this.mergedBeanDefinitions:根据子beanName获取该子bean和父bean合并后的BeanDefinition

	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		// 查看合并BeanDefinition缓存中是否已经存在该BeanDefinition
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null && !mbd.stale) {
			return mbd;
		}
		//根据beanName和BeanDefinition获取合并BeanDefinition
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

getMergedBeanDefinition:设置个参数而已,默认非内嵌bean

	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
			throws BeanDefinitionStoreException {
		return getMergedBeanDefinition(beanName, bd, null);
	}

getMergedBeanDefinition

若存在父标签则合并parent标签,不存在则直接将BeanDefinition转换为RootBeanDefinition

getObjectFromFactoryBean

该方法中在创建单例bean时因为要检测循环依赖,故逻辑较多;而在创建原型bean时,就直接调用FactoryBean的getObject方法,就简单多了

涉及的属性:
inCreationCheckExclusions:标记一个bean在被加载时不需要检查循环依赖
singletonsCurrentlyInCreation:标记一个bean正在被创建

此处重点分析单例bean的创建

	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		//若FactoryBean本身并且一级缓存存在beanName
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {//锁对象:this.singletonObjects
				//从缓存中获取bean实例
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					//此处调用FactoryBean的getObject方法创建对象
					object = doGetObjectFromFactoryBean(factory, beanName);
					//再次从缓存获取对象,如果缓存已经存在,则直接返回,而不再判断是否需要进行后处理操作
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						/*
						* 总结一下这个else:其实经过上述的过程,object已经实例化并且已经初始化完毕,这个else的作用是进行后处理,后处理涉及修改object属性,也就是存在循环依赖的隐患,故需要进行循环依赖的处理。
						*/
						//缓存中不存在,则判断是否需要后处理
						if (shouldPostProcess) {
							//判断是否存在循环依赖,若true则存在,就直接返回
							if (isSingletonCurrentlyInCreation(beanName)) {
								return object;
							}
							//若不存在循环依赖则进行后处理操作
							//将beanName添加到this.singletonsCurrentlyInCreation中
							//本质上就是记录该bean开始被加载---》避免循环依赖
							beforeSingletonCreation(beanName);
							try {
							//调用用户自定义的一些后处理器进行一些操作
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(...);
							}
							finally {
							//从this.singletonsCurrentlyInCreation中移除beanName
							//即表示bean加载已经结束---》避免循环依赖
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							//若bean是单例则加入缓存
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		//若bean是原型则比较简单了,直接调用getObject方法获取bean,再判断是否需要调用后处理器进行处理
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(...);
				}
			}
			return object;
		}
	}

AbstractAutowireCapableBeanFactory # postProcessObjectFromFactoryBean:后处理器

AbstractAutowireCapableBeanFactory # applyBeanPostProcessorsAfterInitialization

遍历每个BeanPostProcessor 对象进行处理,如果在某个后置处理器将result赋值为空时,则直接终端,返回上一个不为不为空的结果

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

在整个FactoryBean创建过程中,只在后处理器处理时使用了singletonsCurrentlyInCreation 属性,用于标记当时正在创建的beanName,但没有涉及到三级缓存,是因为FactoryBean没有setter注入功能。


版权声明:本文为qq_43459448原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。