`

spring疑难解惑-循环依赖的解决

阅读更多
AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		// 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 != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				mbd.postProcessed = true;
			}
		}

		// 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));
//此处表示是否抛出早期引用,以便循环引用时使用,放在三级缓存的singtonFactories里面
//存在循环引用是采用调用ObjectFactory.getObject
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory<Object>() {
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				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) {
//此处从二级缓存的earlySingtonObjects中获取,如何不为空表示,存在循环引用
//在doGetBean方法中,会将三级缓存的singtonFactories调用ObjectFactory.getObject放入到二级缓存的earlySingtonObjects中
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
//如果相等表示,早期引用的bean(即设置到其他bean中的bean引用即为此处的早期引用)
//因为exposedObject = earlySingletonReference;最终都是一个引用
//事务代理属于此类循环引用的实例,事务代理时在AbstractAutoProxyCreater的早期引用中创建的
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
//如果能够容忍创建的bean有多个版本,则可以设置allowRawInjectionDespiteWrapping=true,但这样就破换了spring的单例原则,不建议使用
//hasDependentBean此处表示是否存在引用创建中的bean的其他bean(姑且是beanOther),如果存在则beanOther引用了bean的早期引用,与最终生成的bean是不一致的,肯定不对
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
//此处的TypeCheckOnly=true的场景暂时没有想到待补充,也请路过的博友能够指点一二
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

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

		return exposedObject;
	}



DefaultSingletonBeanRegistry#getSingleton
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);
// 该singletonFactory不为空,在doCreateBean阶段已经放入了ObjectFactory
//此处调用getObject方法生成早期引用,并放入二级环境earlySingletonObjects
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}





AbstractAutoProxyCreator#
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
//此处this.earlyProxyReferences中放入参与早期引用的缓存,在postProcessAfterInitialization中就不用再次创建了,保证了doCreateBean中exposedObject == bean
//他们生成的代理功能本质上是一样的都是getAdvicesAndAdvisorsForBean获取的切面
//但仅限于AbstractAutoProxyCreator的子类生成的代理是可以循环引用的,例如事务属于此类
//其他类型的代理或自定义的代理可能没有实现earlyProxyReferences类似功能,导致exposed!=bean
		if (!this.earlyProxyReferences.containsKey(cacheKey)) {
			this.earlyProxyReferences.put(cacheKey, Boolean.TRUE);
		}
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

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


1.为什么要用三级缓存而不用二级缓存
一个设计良好的系统应该不会经常出现循环引用的情况的,在一开始就设置早期引用浪费系统资源;

2.为什么三级缓存中放入ObjectFactory,而不是bean
为了扩展,生成事务代理或其他代理,以便是代理也可以循环引用


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics