背景
项目启动时异常了,出现了BeanCurrentlyInCreationException异常
异常抛出地方的代码
// AbstractAutowireCapableBeanFactory.doCreateBean
if (earlySingletonExposure) {
// 从缓存中获取,注意这里第二个参数是false,也就是说只能从一级缓存、二级缓存中获取
// 因为此时还未放入一级缓存,所以肯定是没有的,只能从二级缓存中获取
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 比较二级缓存中的bean实例是否与初始化后的bean实例相等,此时发现并不相等
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 接下来就会判断这个bean是否有其他bean进行依赖,如果有则说明注入到其他bean的依赖不是最终包装过后的bean
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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
出现的原因
bean的创建过程
- 在创建对象A的时候,填充属性之前会提前暴露对象A在三级缓存中
// 三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 在bean在实例化时,提前将还未完全实例化好的早期bean通过缓存向外界暴露
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
- 在填充对象A属性时发现依赖了对象B,会尝试从缓存中获取对象B
- 在创建对象B后,填充属性时发现依赖了对象A,会尝试从缓存中获取对象A
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
public Object getSingleton(String beanName) {
// allowEarlyReference 为true
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
// bean 未实例化,并且正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
// 早期缓存对象为空并且 allowEarlyReference 为 true
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存获取早期单例的工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 执行getObject
singletonObject = singletonFactory.getObject();
// 放入早期
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
1. 然后将A注入到对象B中
2. 对象B完成创建、初始化后,继续A的流程,将对象B注入到对象A属性中。
3. 对象A进行初始化
那么加@Async注解之后,为什么会异常
// 从三级缓存获取factoryBean 之后执行getObject
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 实现了 SmartInstantiationAwareBeanPostProcessor
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
AsyncAnnotationBeanPostProcessor并没有实现SmartInstantiationAwareBeanPostProcessor所以getEarlyBeanReference并不会处理
AsyncAnnotationBeanPostProcessor是在bean实例化之后处理生成代理类
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
、、、省略、、、
}
// 判断一下bean是否能匹配到对应类型的advisor
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
// 创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
**@Transactional循环依赖时为什么不会启动异常**
// 代理对象的早期引用
private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 加入集合
this.earlyProxyReferences.add(cacheKey);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
、、、省略、、、
// 获取匹配的 advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
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;
}
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 集合中没有才会进行包装
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
解决
-
避免循环依赖,把
@Async的方法单独处理 -
用
@Lazy注解
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
if(){
、、、省略、、、
}
else {
// @Lazy标识的属性,生成懒加载的代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
// 没有@Lazy标识,getBean
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
// @Lazy标识的属性,生成代理类返回
return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
}