什么是循环依赖?
循环依赖就是两个或者多个bean之间相互依赖,形成依赖闭环. 例子: A对象包含属性B,B对象包含属性A,如下图:
spring在处理循环依赖的问题上采用了三级缓存
三级缓存在bean创建的那个时机会用到?
1.bean实例化之前会查询缓存,判断bean是否已经存在
2.bean属性赋值之前会先向三级缓存中放入一个lambda表达式,该表达式执行则会生成一个半成品Bean放入二级缓存
3.Bean初始化完成后将完整的Bean放入一级缓存,同时清空二、三级缓存
bean创建的过程:
以上三个时机的源码分析
1. bean实例化之前
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从singletonObjects(一级缓存)中获取,获取不到继续往下走
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
//从earlySingletonObjects(二级缓存)中获取,获取不到继续往下走
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//为了线程安全加锁
synchronized(this.singletonObjects) {
//从一级缓存中获取,获取不到往下走
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//从二级缓存中获取,获取不到往下走
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//从三级缓存中获取lambada表达式
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//根据lambada表达式获取bean
singletonObject = singletonFactory.getObject();
//将获取到的bean放入二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
整体逻辑总结为:
- 从一级缓存获取,获取到了,则返回
- 从二级缓存获取,获取到了,则返回
- 从三级缓存获取,获取到了,则执行三级缓存中的lambda表达式,将结果放入二级缓存,清除三级缓存
2. bean属性赋值之前
AbstractAutowireCapableBeanFactory#doCreateBean
addSingletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
//如果一级缓存中不存在的话,往下走
if (!this.singletonObjects.containsKey(beanName)) {
//放入三级缓存
this.singletonFactories.put(beanName, singletonFactory);
//删除二级缓存中对应的bean
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
AbstractAutowireCapableBeanFactory#getEarlyBeanReference
该方法逻辑:判断该Bean是否需要被动态代理
- 不需要代理,返回未属性注入、未初始化的半成品Bean
- 需要代理,返回未属性注入、未初始化的半成品Bean的代理对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var5 = this.getBeanPostProcessors().iterator();
// 遍历后置处理器
while(var5.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var5.next();
// 找到实现SmartInstantiationAwareBeanPostProcessor接口的
// 该接口getEarlyBeanReference方法什么时候会执行?
// AOP动态代理的时候 该方法执行就是判断该Bean是否需要被代理
// 需要代理则会创建代理对象返回
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
// 这个Object有两种情况,一是实例化后的半成品Bean,二是半成品Bean动态代理后的代理对象
return exposedObject;
}
注意:这里只是把lambda表达式放入了三级缓存,如果不从三级缓存中获取,这个表达式是不执行的,一旦执行了,就会把半成品Bean或者半成品Bean的代理对象放入二级缓存中了
3. Bean初始化完成后
AbstractBeanFactor#doGetBean
这里注意啊,这个getSingleton方法传参传了个lambda表达式,这个表达式内部就是Bean的实例化过程,初始化完成后,是要需要执行这个getSingleton方法的
DefaultSingletonBeanRegistry.getSingleton(beanName, singletonFactory)
这个方法与上面那个不一样,重载了
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized(this.singletonObjects) {
// 第一次进来这里获取肯定为null
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 省略................
try {
// 注意啊,这个就是执行外面那个传参的lambda表达式
// 所以这里才会跳到createBean方法那里去执行
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// 省略................
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
// 到了这说明Bean创建完了
if (newSingleton) {
// 这里就会把Bean放入一级缓存中了 同时清除二、三级缓存
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
DefaultSingletonBeanRegistry#addSingleton
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);
}
}
总结:
整个过程就三个地方跟缓存有关,我们假设现在要实例化A这个Bean,看看缓存是怎么变化的:
实例化前,获取缓存判断(三个缓存中肯定没有A,获取为null,进入实例化流程)
实例化完成,属性注入前(往三级缓存中放入了一个lambda表达式,一、二级为null)
初始化完成(将A这个Bean放入一级缓存,清除二、三级缓存)
一级缓存,存放完整bean:
Map<String, Object> singletonObjects
二级缓存,存放半成品bean:
Map<String, Object> earlySingletonObjects
三级缓存,存放工厂对象(lambda表达式):
Map<String, ObjectFactory<?>> singletonFactories