1.下面三个缓存容器(ps:为什么三级缓存不是concurrentHashMap,我也不知道,请大佬解惑)
缓存逻辑:实例化A之后,并且将beanFactory放到三级缓存中,然后执行populateBean属性注入
1.如果其他Bean没有引用这个A,那么就不会从三级缓存获取BeanFactory,和调用BeanFactory的getObject方法了,二级缓存此时就不会用到。populateBean执行完成之后就直接bean放到一级缓存中,清除其他两个缓存
2.如果有循环依赖,populateBean执行的时候就会,去三级缓存获取BeanFactory,然后调用beanFactory的 getObject方法生成代理对象,并加入到二级缓存中,属性注入完成,从二级缓存获取bean,然后加入到一级缓存并清空其他两个缓存
注意:没有存在循环依赖的话,代理对象是在初始化完成后进行的,如果有循环依赖,那么代理对象在属性注入阶段就被创建了,这样才能将代理对象注入到其他对象中。
/** Cache of singleton objects: bean name to bean instance. 一级缓存 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of early singleton objects: bean name to bean instance. 二级缓存 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** Cache of singleton factories: bean name to ObjectFactory. 三级缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
2.创建bean主要的方法是在AbstractBeanFactory.doGetBean方法关键的方法就是getSingleton这两个重载的方
1.1 从三个缓存中获取bean
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//没有获取到,加锁再重新获取
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
//一级缓存获取
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//三级缓存获取,存的是ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
1.2 没有缓存中获取到bean的话,接下就会调用另一个重载的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) {
//实例化前的校验,是否正在创建,正在创建的话会抛出异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//创建bean的关键入口,里面的主要的逻辑代码在AbstractAutowireCapableBeanFactory.doCreateBean方法中
//创建好bean实例之后,会接着放到三级缓存中
//addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
//add方法主要逻辑将1.ObjectFactory放到三级缓存 2.移除二级缓存
//getEarlyBeanRefrence主要就是调用SmartInstantiationAwareBeanPostProcessor接口实现,
//代理类就是在这一步去处理的(这个地方不会执行这个逻辑,在获取三级缓存的时候,
//得到ObjectFactory对象调用getObject方法才会执行(singletonObject = singletonFactory.getObject();)
//情况1.如果它的属性对象也引用了它,就出现了循环依赖。比如A、B互相依赖,当前是A,A实例化
//了,执行populateBean属性注入,执行B的实例化过程,B实例化然后执行populateBean,去获取A,从1.1的代码,
//走到三级缓存,从三级缓存中获取ObjectFactory,然后getObject执行一些列代理接口,得到最终的bean,并把bean放到二级缓存
//情况2.如果对象没有循环依赖,这个在下面这个方法执行完成后还是在三级缓存中
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
//异常捕捉代码省略
..........
}
if (newSingleton) {
//下面四行注释是addSingleton方法copy出来的,将bean放到一级缓存中,移除三级缓存和二级缓存中的数据。上面说了两种情况,有循环依赖的话此时bean在二级缓存,没有循环依赖的话在三级缓存,这个地方没有从三级缓存拿的话,岂不是代理逻辑就没了
//this.singletonObjects.put(beanName, singletonObject);
//this.singletonFactories.remove(beanName);
//this.earlySingletonObjects.remove(beanName);
//this.registeredSingletons.add(beanName);
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}