循环依赖 老生常谈了 这里大概描述一下场景和把代码重点标注出来
名词介绍
一级缓存(单例池):singletonObjects
二级缓存(存的是工厂方法):singletonFactories
三级缓存:earlySingletonObjects
1 场景介绍
1 A注入B B注入A
A --将A放入二级缓存-A的ioc ----实例化B-将B-放入二级缓存-B-的ioc--将A从二级缓存拿出--执行A的aop--将A从二级缓存放入三级缓存---B实例化完了--放入一级缓存---继续A的ioc--A实例化完了 将A从三级缓存放入一级缓存
2 正常A注入B
A--将A放入二级缓存-A的ioc ----实例化B-将B-放入二级缓存-B-的ioc--B实例化完毕后--将B放入一级缓存---继续A的实例化--A实例化完,将A放入一级缓存
重点
1这2者差距是 三级缓存只有循环依赖的时候 才会将A放入三级缓存 正常就是先放入二级缓存再升级为一级缓存
2 二级缓存放的是工厂方法 只有出现了循环依赖才会调用 提前生成aop对象 目的就是为了B中注入的A是一个proxy代理对象 而不是target被代理对象
3 只有二级升级为三级 或者 一级 , 三级升级为一级 这2种升级 ,二级升级为三级是循环依赖才胡升级 ,三级升级为一级 就是上面的A注入B,B实例化完后 ,A才会升一级,正常都是二级升级为一级
4 spring为啥要三级 本身二级是可以搞定循环依赖 但是循环依赖的时候 没有第二级缓存 就没发提前把依赖对象给Aop 导致注入的是不是一个代理对象
代码具体地方
A--实例化,在doGetBean的第一步先去缓存中拿A
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
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;
}
此时A第一次实例化 肯定不在一级缓存和不是当前正在创建 于是这个方法返回null,继续往下走
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);
}
于是走到这里 会先走到getsingleton
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 (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
这个方法中开始从一级缓存拿 肯定拿不到 继续走 beforeSingletonCreation会将A置为正在创建中,接下来会走到外面传的lamda表达式也就是开始createBeanA,走到docreateBean里面后有这么一段代码 会将A添加到二级缓存
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);
});
}
这个getEarlyBeanReference是一段lamda表达式(工厂方法) 此时并不会执行,这时候A被置为了创建中和放入了二级缓存,这时候开始对B进行注入 发现B都没注入 开始实例化B,跟A一样会走到这里那么B也会置为了创建中和放入了二级缓存,开始对b进行Ioc,发现要注入A,然后就会去getBean-A 然后就会走到getBean的getSingleton
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
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;
}
这时候 A不在一级缓存中 进了if ,条件也满足 于是去三级缓存中拿A这时候 A还在二级缓存呢,于是调用了A的getEarlyBeanReference方法 这时候A假如有Aop 就会提前生成代理,于是A就被放到了三级缓存从二级缓存中挪走了,于是返回给B的A这个field,b于是ioc完了 b这个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 (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
里面有个
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
将b从二级缓存中挪出 升级为一级缓存
接下来继续回到A A继续实例化 然后也跟b一样 实例化完了后 从三级缓存挪出 变成一级缓存
总结
1 getBean里的getSinleton只会是循环依赖时候将二级升级为三级,并且执行二级缓存的工厂方法,提前aop,正常从一级缓存直接拿了
2 createBean后的添加缓存是会将有循环依赖的A从三级升级为一级的,正常的B就是二级升级为一级
3 不管是A还是B 在进行ioc之前都会放入二级缓存