spring实例化bean之循环依赖

serviceA里注入了serviceB,serviceB里又注入了serviceA,这样在实例化serviceA时,在doCreateBean时的populateBean时会先实例化serviceB,然后实例化serviceB,在serviceB的doCreateBean方法的populateBean又会去找servcieA,这样循环依赖就产生了。
解决办法就是在populateBean之前把当前的serviceA提前暴露,然后在实例化B时可以找到这个提前暴露的serviceA。
关键方法是doCreateBean方法中的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

实例化serviceA,调用getSingleton。

1. DefaultSingletonBeanRegistry#getSingleton

这里就是对当前bean做了一个标志,在实例化前表明当前bean在创建中,在实例化后删除这个标志

	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 + "'");
				}
				//关键1 标志A这个Bean在创建中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					//调用createBean方法
					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;
					}
					//关键2 //this.singletonsCurrentlyInCreation.remove(beanName)
					//删除掉Bean A创建中的标识
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

实例化serviceA,创建bean。

2. 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;
		}

		// 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.
		//这里如果是单例 并且允许循环依赖(配置文件配置) 并且是正在创建的bean(1中设置)
		//能满足这个三个条件,则Spring会认为这个此时A是需要提前暴漏的单例Bean
		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)) {
					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 " +
								"'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;
	}

3. DefaultSingletonBeanRegistry#addSingletonFactory

实例化A时,doCreateBean方法populateBean方法执行之前,也就是实例化注入的serviceB之前会调用这个方法。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				//把当前bean 也就是serviceA关联一个singletonFactory(也就是那个lambda表达式)
				this.singletonFactories.put(beanName, singletonFactory); //三级缓存
				this.earlySingletonObjects.remove(beanName); //二级缓存
				this.registeredSingletons.add(beanName);
			}
		}
	}

给A关联了一个ObjectFactory,也就是getEarlyBeanReference对应的lambda函数对象。放入了singletonFactories中,当B去查BeanA的时候就可以通过getEarlyBeanReference方法获取exposedObject这个早期bean对象。

4.AbstractAutowireCapableBeanFactory#getEarlyBeanReference

这里基本就是把传入的bean返回。命名为exposedObject 早期暴露对象
调用逻辑就是 serviceB实例化时需要注入serviceA,然后在doGetBean的最开始调用getSingleton方法时会获取到serviceA的ObjectFactory,然后执行singletonFactory.getObject()就会执行这个方法拿到bean。

	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//这个的作用是当前循环依赖的bean恰巧是AOP类型的bean,这里会获取到该bean的代理对象,
				//保证最终实例化的bean和依赖引入的bean是相同的,都是代理类型。
				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				}
			}
		}
		//如果是普通的bean就直接返回了。
		return exposedObject;
	}

查找
比如在实例化serviceA时需要实例化serviceB,实例化serviceB时populateBean方法会再尝试实例化serviceA,doGetBean方法开始会调用getSingleton方法,这个方法里会找到提前暴露的serviceA,保证serviceB可以顺利创建。

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//这里获取不到 因为servcieA的实例化还没完成 也就是servcieA的createBean方法还没执行完,servcieA的getSingleton方法的
		//singletonObject = singletonFactory.getObject()方法也就没执行完,下面的addSingleton方法
		//就不会执行(在这里执行this.singletonObjects.put(beanName, singletonObject)),	
		//singletonObjects中就不会有serviceA。 一级缓存
		Object singletonObject = this.singletonObjects.get(beanName);
		//判断会通过 第二个判断条件是在getSingleton方法的beforeSingletonCreation(beanName)设置的 最开始实例化A时会调用
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				//这里也获取不到,因为在最开始servcieA实例化时的addSingletonFactory方法会执行
				//this.earlySingletonObjects.remove(beanName); 二级缓存
				singletonObject = this.earlySingletonObjects.get(beanName);
				//判断会进入
				if (singletonObject == null && allowEarlyReference) {
					//这里能获取到,因为在servcieA实例化时的addSingletonFactory方法会执行
					//this.singletonFactories.put(beanName, singletonFactory); 三级缓存
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//执行这个方法会执行那个lambda表达式 () -> getEarlyBeanReference(beanName, mbd, bean)
						//获取到serviceA
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		//获取到返回 此时serviceB就可以得到serviceA了,然后继续创建serviceB
		return singletonObject;
	}

总结
实例化过程:
1.finishBeanFactoryInitialization(beanFactory);
2.beanFactory.preInstantiateSingletons();
3.getBean(beanName);
4.doGetBean
在这里插入图片描述

这里实例化serviceA时找不到,但是在实例化注入的serviceB时又需要实例化serviceB注入的serviceA,这时就可以获取到serviceA了。
5.
在这里插入图片描述
这里的getSingleton方法在执行时执行到**singletonObject = singletonFactory.getObject()**时就会执行lambda表达式的createBean方法。
依赖关系的处理是在createBean方法的doCreateBean方法的populateBean方法
6.doCreateBean
在这里插入图片描述
关键方法

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

这个方法在实例化serviceA,populateBean之前,把serviceA及关联的ObjectFactory(lambda表达式)加到了singletonFactories,这样serviceB实例化时需要实例化servcieA,在doGetBean一开始的getSingleton方法会获取到serviceA,这样就能保证serviceB能创建完成,然后再创建serviceA。

在这里插入图片描述
springboot2.6之后默认禁用循环依赖。
在这里插入图片描述
在这里插入图片描述
开启的话需要增加配置:
spring.main.allow-circular-references=true

注意:
@Validated会导致允许循环依赖的配置失效
添加@lazy
属性填充时 DefaultListableBeanFactory#resolveDependency方法针对@lazy注解有不同的处理,
如果加了注解就不走getbean获取依赖的bean,直接返回一个代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值