Spring中循环引用的处理-2

上文中对涉及到循环引用的3个方法作了陈述。

在方法1中,对象信息对beanFactory的形式被放入singletonFactories中,这时earlySingletonObjects中肯定没有此对象(因为remove)。

在方法2中,在一定条件下(allowEarlyReference为true)的条件下,对象从singleFactories中的objectFactory中被取出来,同时remove掉,被放入earlySingletonObjects中。这时,earlySingletonObjects就持有对象信息了;当然,如果allowEarlyReference为false的情况下,且earlySingletonObjects本身就没有持有对象的情况下,肯定不会将对象从objectFactory中取出来的。这个很重要,因为后面将根据此信息进行循环引用处理。

在方法3中,对象被加入到singletonObjects中,同时singletonFactories和earlySingletonObjects中都remove掉持有的对象(不管持有与否),这就表示在之前的处理中,这只相当于一个临时容器,处理完毕之后都会remove掉。

那么,我们来看这3个方法是不是按照先后顺序被调用的呢。代码顺序如下所示:

类AbstracBeanFactory获取bean。M-1

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
					public Object getObject() throws BeansException {
						try {
							return createBean(beanName, mbd, args);
						}				……
}

进入getSingleton方法M-2

Object singletonObject = this.singletonObjects.get(beanName);
				try {
//首先执行getObject方法,再执行finnaly中的addSingleton方法,即上文中的方法3
					singletonObject = singletonFactory.getObject();
				}finally {
addSingleton(beanName, singletonObject);
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}

查看singletonFactory.getObject(),即createBean(beanName, mbd, args),最终转向doCreateBean方法M-3

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
					instanceWrapper = createBeanInstance(beanName, mbd, args);
			addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

上面代码会调用方法addSingletonFactory,即上文所说的方法1。
那么方法2会在什么地方调用呢。答案在两个地点。

第一个地方,称之为调用点A,即在最开始获取bean时,会调用。

Object sharedInstance = getSingleton(beanName);

此方法最终会调用到

getSingleton(beanName, true)

这里传递了参数true。即会尝试解析singletonFactories。然而,在最开始创建对象时,singletonFactories中肯定不会持有对象信息,所以会返回null。

第二个地方,称之为调用点B,即在完成bean创建时,会有一个验证过程。即在方法M-3中,即在调用方法2之前。代码如下:

if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw 文章开头的异常。
					}
				}
			}

调用点B的逻辑有点多,后面的逻辑主要是作循环引用验证。注意在调用点B传递参数为false,即不会解析singletonFactories。

详细见下一篇
Spring中循环引用的处理-3

前一篇
Spring中循环引用的处理-1

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201208280002.html

相关文章:

作者: flym

I am flym,the master of the site:)

《Spring中循环引用的处理-2》有一个想法

  1. 我特意去翻了翻代码比对一下,建议省略的地方用*号表示

发表评论

电子邮件地址不会被公开。 必填项已用*标注