Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
com.lwq.spring.ioc.circular_reference.StudentA@2d928643
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
......
// 创建对象(执行构造器(new))
instanceWrapper = createBeanInstance(beanName, mbd, args);
......
// 属性注入(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
......
// 初始化方法(为Bean实例对象添加BeanPostProcessor后置处理器的入口就是这个initializeBean方法。)
exposedObject = initializeBean(beanName, exposedObject, mbd);
......
}
见源码 DefaultSingletonBeanRegistry#singletonsCurrentlyInCreation
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
......
// 将当前bean放入“正在创建的bean”集合中
beforeSingletonCreation(beanName);
......
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Cache of singleton objects: bean name to bean instance. */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
private final Map earlySingletonObjects = new HashMap<>(16);
......
}
protected T doGetBean(
......
// 原型bean的创建
else if (mbd.isPrototype()) {
......
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
......
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
......
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
......
// 创建对象(执行构造器(new))
instanceWrapper = createBeanInstance(beanName, mbd, args);
......
// 如果是单例bean,并且允许循环依赖,并且当前bean正在“正在创建的bean”集合中,则将该bean放入三级缓存
// 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));
}
......
// 属性注入(依赖注入)
populateBean(beanName, mbd, instanceWrapper);
......
// 初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
......
}
//创建Bean的实例对象
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
......
// 有参构造方法进行属性注入
autowireConstructor(beanName, mbd, ctors, args);
......
}
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor>[] chosenCtors, @Nullable Object[] explicitArgs) {
......
// 构造参数解析注入
resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
......
}
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
Executable executable, Object[] argsToResolve, boolean fallback) {
......
// 解析属性值,对注入类型进行转换
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
......
}
// 属性注入
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
......
// /解析并注入依赖属性的过程
applyPropertyValues(beanName, mbd, bw, pvs);
......
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
......
// 解析属性值,对注入类型进行转换
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
......
}
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
......
// 对引用类型的属性进行解析
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
// 对属性值是引用容器中另一个Bean名称的解析
else if (value instanceof RuntimeBeanNameReference) {
......
}
//对Bean类型属性的解析,主要是Bean中的内部类
else if (value instanceof BeanDefinitionHolder) {
......
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
......
//从当前的容器中获取指定的引用Bean对象,如果指定的Bean没有被实例化,则会递归触发引用Bean的实例化和依赖注入
bean = this.beanFactory.getBean(refName);
this.beanFactory.registerDependentBean(refName, this.beanName);
......
}
有了这些结论,可以接着往下分析了:
BeanCurrentlyInCreationException,就是结果看到的错误了。所以构造器注入单例bean的循环依赖,会直接出错,无法循环依赖
所以setter方法注入单例bean的循环依赖是可以成功的,关键就在三级缓存的设计。
至于二级缓存的设计目的 是为了解决共同依赖时从三级缓存获取同一bean出现的不是同一实例的问题,如:
a同时依赖b和c,b依赖a,c依赖a,那么a注入b,c时,因为b,c都依赖a,就需要从三级缓存获取a,假如恰巧b,c同时去三级缓存获取a(a还没正式创建完成),他们得到的将是两个实例(因为三级缓存获取bean其实就是工厂实时生成一个bean),这与a单例的意图是有冲突的。而有了二级缓存,就可以在不管是b或者c在第一次从三级缓存获取a时,顺便将a移动到二级缓存,后面c或者b再获取a时,实际是从二级缓存拿到的同一实例。
很简单原型(prototype)bean是不缓存在spring容器中的,每次使用时都是生成新的实例。
先实例化,再初始化。