在spring创建bean的过程,如果出现了A依赖B,并且B依赖A的情况,那么这种情况称之为循环依赖。spring并不能够解决构造器注入的循环依赖,只能解决属性的循环依赖。
spring创建bean,首先会调用doGetBean方法
1.从容器中获取单例的bean
2.如果不存在单例的bean,那么进行bean的实例化
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
//从容器中获取单列bean
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//没有获取到,则进行bean的的初始化
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
return bean;
}
getSingleton方法获取bean的过程,采取了三级缓存的方式
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
private final Map<String, Object> earlySingletonObjects = new HashMap(16);
首先从singletonObjects 中获取,如果不存在再去earlySingletonObjects 中获取,再没有才去singletonFactories 获取。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从singletonObjects容器中获取bean
Object singletonObject = this.singletonObjects.get(beanName);
// singletonObjects容器没有bean,并且当前bean在创建过程中
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
//从earlySingletonObjects容器获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
//如果earlySingletonObjects没有并且allowEarlyReference为true
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
单例bean初次创建时,会进入到下述方法,这个方法才去了匿名内部类的方式作为singletonFactory的形参,这样的话会首先执行getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,再去执行匿名内部类里面的this.createBean(beanName, mbd, args)方法
getSingleton方法的主要内容在于beforeSingletonCreation,该方法会在容器中插入当前需要创建bean的beanName,标识当前bean已经在创建
Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16))
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized(this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
this.beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
return singletonObject;
}
}
然后使用到singletonFactory,所以需要执行匿名内部类中的createBean方法,可以看到createBean依次做了如下事情:
- 创建bean的实例
- 将创建好的bean放入singletonFactories 中,供其他bean引用
- 依赖注入
- 完成初始化并返回
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//创建bean实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
// 当前bean为单例,允许早起引用并且isSingletonCurrentlyInCreation为true的情况,addSingletonFactory将bean放入singletonFactories ,以便接下来依赖注入的时候可以获取到bean。其中isSingletonCurrentlyInCreation在getSingleton(String beanName, ObjectFactory<?> singletonFactory)的时候已经设置过。
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.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.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}