doCreateBean方法中BeanCurrentlyInCreationException解析

	   populateBean(beanName, mbd, instanceWrapper);
	   exposedObject = initializeBean(beanName, exposedObject, mbd);	
        。。。。	
       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.");
					}
				}
			}
		}

bean :原始对象

exposedObject :初始化后的对象,可能为代理对象

earlySingletonReference :实例化但未初始化的对象,可能为代理对象。Object earlySingletonReference = getSingleton(beanName, false),可以从getSingleton源码中看出,当allowEarlyReference为false时,只在一二级缓存获取值,而二级缓存的值是三级缓存赋值的,若一个对象不存在循环引用,则永远不会从三级缓存中取值赋值到二级缓存中,那么earlySingletonReference是null。

        要触发BeanCurrentlyInCreationException,说明exposedObject为代理对象,即在initializeBean方法中bean被代理了。而如果该bean是循环引用的对象,例如A对象(A->B->A),因为执行到此处代码时,B对象已经完全初始化了,而B中引用的A则是从三级缓存中获取到的A对象,但A对象在B初始化完后又进行了一次代理,造成B中的A和A初始化后的A不一样,就会触发该异常。spring是通过下方if判断进行检查,

                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }

该if检查可总结为:如果某个对象初始化后进行了一次代理,而该对象初始化之前已被其它完成初始化的对象引用,则会触发该异常。

@Async 的处理就是在初始化后进行了一次代理,如果对应的bean循环依赖,就会触发该异常

@Transactional  对应的bean若循环依赖,因为该bean对应的代理是在从三级缓存中获取时处理的,而在初始化后exposedObject依旧是原始的bean对象,所以exposedObject和bean相等,此时会从二级缓存中取出代理对象赋值给exposedObject,所以最终返回的exposedObject为代理对象,不会出现该异常。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值