Spring 循环依赖概念
在Spring容器中,对Bean对象的创建并不是简单的new出来就完成,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期所以才会出现循环依赖的问题,比如:Spring在创建一个AService Bean对象,AService经过Bean的生命周期,在进行属性注入(依赖注入)时需要注入BService,此时会去Spring容器的单例池中查找BService对象,如果此时单例池没有BServcie对象,Spring容器则去创建BService的Bean对象,在创建BService Bean对象,经过Bean的生命周期,在进行属性注入(依赖注入)时,BService有个属性AService,需要注入AService对象而AService对象正在创建过程中,此时就出现了循环依赖的问题。

在Spring中,出现循环依赖的场景很多,有的场景Spring自动帮我们解决了,而有的场景则需要程序员来解决。
Spring 三级缓存解决循环依赖
在Spring中,采用三级缓存的机制来帮助开发者解决了部分循环依赖的问题,三级缓存是一个通用的叫法,三级缓存分为以下三种Map:
一级缓存:singletonObjects
二级缓存:earlySingletonObjects
三级缓存:singletonFactories
解决思路分析
上述场景出现的循环依赖,Spring解决思路分析

Spring在创建AServicce对象时,会先实例化一个AService的原始对象,使用AService的原始对象去生成一个ObjectFactory,这个ObjectFactory就是一个lambda表达式(() -> getEarlyBeanReference(beanName, mbd, bean)),将这个ObjectFactory对象存入singletonFactories(三级缓存),此时并不会执行lambda表达式即不会执行getEarlyBeanReference方法。
AService对象在进行属性赋值(依赖注入)时,需要给bService属性注入BService对象值,首先从Spring容器的单例池中找BService对象,没有找到,则创建BService对象,在进行创建BService Bean的生命周期中进行依赖注入,此时需要注入aService属性值。
从singletonFactories中获取beanName对应的ObjectFactory,然后执行ObjectFactory,也就是执行getEarlyBeanReference方法,此时会得到AService原始对象经过AOP之后的代理对象,把代理对象放入earlySingletonObjects(二级缓存)中。继续执行BService Bean对象的生命周期步骤,完成BService对象的创建。
当BService对象创建完成后,AService对象继续进行生命周期,在AService对象完成属性注入后,会按照本身的逻辑进行AOP,而此时的AService对象已经经历了AOP,Spring底层会利用earlyProxyReferences,去判断当前beanName是否在earlyProxyReferences,如果在则表示提前进行了AOP了,无需再次进行AOP。
对于AService而言,进行了AOP的判断后及BeanPostProcessor的执行之后,就需要把AService对应的对象放入singletonObjects(一级缓存)单例池中,所以此时需要从earlySingletonObjects中得到代理对象,然后放入singletonObjects中。
Spring 解决循环依赖实现源码
AService 原始对象创建
AService对象创建,经过Bean生命周期,将AService对象正在创建beanName缓存到Set alreadyCreated中,实例化得到一个AService的原始对象,实现源码位于 AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建Bean实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 后置处理合并后的BeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
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));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("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) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
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 " +
"'getBeanNamesForType' 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;
}ObjectFactory添加到singletonFactories
利用AService的原始对象生成一个ObjectFactory(是一个lambda表达式,具有getEarlyBeanReference方法),将这个ObjectFactory缓存在singletonFactories(三级缓存)
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}AService 属性依赖注入
AService Bean对象进入依赖注入的生命周期步骤,此时需要对BService属性值进行赋值,会拿BService这个名字去Spring容器(单例池)中查找,没找到,则进行BService对象的创建,具体实现源码位于AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//......
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}调用AutowiredAnnotationBeanPostProcessor#postProcessProperties方法查找注入点
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 找注入点(所有被@Autowired注解了的Field或Method)
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}调用InjectionMetadata#jinect方法遍历所有的注入点依赖注入,注入点可能是:AutowiredFieldElement、AutowiredMethodElement,具体可看Spring Bean依赖注入。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
// 遍历每个注入点进行依赖注入
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}BService 原始对象创建
在AService对象进行属性注入时存在BService属性,需要获取BService对象,Spring底层实现中先从单例池获取BService对象,如果不存在,则创建BService对象,Spring进行BService创建的生命周期,创建得到一个BService的原始对象,其底层实现和AService原始对象创建、ObjectFactory添加到singletonFactories一致,只是创建的Bean对象不同。
BService 属性依赖注入
BService对象生命周期进入依赖注入步骤,BService对象拥有AService的属性,这时Spring在单例池获取AService对象时,getSingleton(String beanName,boolean allowEarlyReference)中进行判断获取AService对象是否在创建中,此时就能判断出bean是否出现了循环依赖。Spring底层实现源码入口位于AbstractBeanFactory#doGetBean方法。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx
// name有可能传入进来的是别名,那么beanName就是id
String beanName = transformedBeanName(name);
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
//......
}上面的getSingleton(beanName)方法会调用DefaultSingletonBeanRegistry#getSingleton方法
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
在下面方法源码中,会从singletonFactories(三级缓存)中获取AService的ObjectFactory对象,调用getObject()方法会执行lambda表达式中的getEarlyBeanReference方法。
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) {
//执行lambda表达式中的getEarlyBeanReference方法
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}getEarlyBeanReference方法调用,源代码位于AbstractAutowireCapableBeanFactory#getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}最终调用AbstractAutoProxyCreator#getEarlyBeanReference方法,在此方法类会将beanName缓存在earlyProxyReferences中,调用wrapIfNecessary方法进行是否需要进行AOP,如果需要进行AOP,会进行AOP操作生成代理对象,不需要进行AOP则直接返回原始对象。
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// advisedBeans记录了某个Bean已经进行过AOP了
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}循环依赖解决完毕
BService对象生命周期依赖注入步骤完成后,进行后续的生命周期操作步骤,最终将BService创建的Bean对象放入Spring的singletonObjects(单例池)中,AService对象完成属性注入后,继续进行后续的生命周期,在进行初始化之后的步骤,会按照本身的逻辑去进行AOP,此时AService对象已经经历了AOP操作,那么在postProcessAfterInitialization方法中会去判断earlyProxyReferences缓存中是否存在AService的key,如果存在表示已经进行了AOP,无需再次进行AOP。Spring底层实现源码位于AbstractAutoProxyCreator#postProcessAfterInitialization方法中。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}对于AService对象而言,进行了AOP的判断及BeanPostProcessor的执行之后,就需要把AService对应的对象放入singletonObjects(单例池)中,所以此时需要从earlySingletonObjects(二级缓存)中得到代理对象,然后放入singletonObjects中。此时整个循环依赖解决完毕。Spring底层实现源码位于AbstractAutowireCapableBeanFactory#doCreateBean方法中
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//......
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
//......
}总结
Spring采用三级缓存的机制解决了循环依赖的问题,对三级缓存进行总结:
singletonObjects:缓存经过了完整生命周期的bean。
earlySingletonObjects:缓存未经过完整生命周期的bean,如果某个bean出现了循环依赖,就会提前把这个暂时未经过完整生命周期的bean放入earlySingletonObjects中,这个bean如果要经过AOP,那么就会把代理对象放入earlySingletonObjects中,否则就是把原始对象放入earlySingletonObjects,但是不管怎么样,就是代理对象,代理对象所代理的原始对象也是没有经过完整生命周期的,所以放入earlySingletonObjects我们就可以统一认为是未经过完整生命周期的bean。
singletonFactories:缓存的是一个ObjectFactory,也就是一个Lambda表达式。在每个Bean的生成过程中,经过实例化得到一个原始对象后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式可能用到,也可能用不到,如果当前Bean没有出现循环依赖,那么这个Lambda表达式没用,当前bean按照自己的生命周期正常执行,执行完后直接把当前bean放入singletonObjects中,如果当前bean在依赖注入时发现出现了循环依赖(当前正在创建的bean被其他bean依赖了),则从三级缓存中拿到Lambda表达式,并执行Lambda表达式得到一个对象,并把得到的对象放入二级缓存((如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象))。
earlyProxyReferences:一个缓存用来记录某个原始对象是否进行过AOP了。
文章详细介绍了Spring框架在处理Bean对象循环依赖时的机制,包括Bean的生命周期、三级缓存(singletonObjects、earlySingletonObjects、singletonFactories)的作用,以及如何通过这些缓存解决循环依赖问题。在创建Bean过程中,Spring会先创建原始对象并存入三级缓存,当遇到依赖时,尝试从缓存中获取,如果发现循环依赖,则利用ObjectFactory获取早期引用,完成依赖注入,最后将完全初始化的Bean放入一级缓存。此外,文章还提到了AOP在解决循环依赖中的作用。
3882

被折叠的 条评论
为什么被折叠?



