聊聊源码
在spring 中,解决循环依赖的关键是三级缓存,缓存数据在 DefaultSingletonBeanRegistry类中
/** Cache of singleton objects: bean name to bean instance. */
//一级缓存,是最终生成的对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
//三级缓存,和aop相关
//ObjectFactory 是一个函数式接口,如果有进行aop,则返回aop对象,否则返回的是原始对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
//二级缓存,完成实例化,未完成初始化的对象
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
1 提前暴露
AbstractAutowireCapableBeanFactory#doCreateBean
在这个方法中,spring会将已经完成实例化的bean放入到三级缓存中去。
java
//AbstractAutowireCapableBeanFactory 类
//创建bean的过程
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
//如果是单例,先从缓存中进行获取,如果获取的到,则直接使用
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如果缓存中没有,则创建bean实例
if (instanceWrapper == null) {
//【核心】创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
.... 其他处理逻辑
/******************************* 1 提前暴露 *******************************/
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//判断是否支持循环依赖(是单例 && 允许循环引用 && 当前bean正在创建中)
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");
}
//这个方法会将当前的实例化完成,初始化未完的对象,存储到 singletonFactories 缓存中去
//之所以存到的是三级缓存,是因为对象可能是经过aop的,在singletonFactories中存储的是ObjectFactory
// ObjectFactory是一个函数式接口,如果对象有经过aop会返回aop对象,否则返回原对象
//singletonFactories 就是我们所说的三级缓存
//同时,会将beanName 存入 registeredSingletons 列表中,作用是提前曝光,是解决循环袭来的关键
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//【核心】填充bean的属性
//1 完成属性的注入,根据bean定义的时候,设置的属性值。
//2 解析依赖 如果bean依赖其他的bean,则其会递归的去创建其他的bean
//3 调用BeanPostProcessor,这里主要是执行 InstantiationAwareBeanPostProcessor
populateBean(beanName, mbd, instanceWrapper);
//【核心】初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
... 其他处理逻辑
return exposedObject;
}
2 从缓存中依次获取bean
在populateBean中,会去循环遍历需要进行依赖注入的bean,会通过getBean方法去进行获取,会走到DefaultSingletonBeanRegistry.getSingleton
过程如下
1 从一级缓存中获取,如果可以获取到,直接返回
2 如果一级缓存中获取不到,从二级缓存中获取,如果获取到,则直接返回
3 如果二级缓存也获取不到,则从三级缓存中获取
java
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
//先从一级缓存中获取,一级缓存存放的是成品bean,就是已经完成了实例化和初始化
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//从二级缓存中获取(早期单例缓存),只完成了实例化的bean
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是一个函数式接口,这个方法就是
// AbstractAutowireCapableBeanFactory.getEarlyBeanReference
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
三级缓存中存储的对象是ObjectFactory,这个对象定义的是一个函数式接口,最终会调用回设置的位置,就是
AbstractAutowireCapableBeanFactory的getEarlyBeanReference方法
java
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
//这是一个BeanPosterProcessor,是一个接口
//1 允许获取一个早期的bean
//2 一般框架中,比如mybatis中的事务,会实现这个接口的getEarlyBeanReference方法
//然后返回一个aop之后的类。
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
总结
从源码中,我们可以推断出,循环依赖的处理有几个基础的点,分别是
1 三级缓存,三级缓存中的第三级缓存是处理循环依赖的关键
2 提前暴露,在bean完成实例化之后,spring就会将还未创建完成的bean暴露到三级缓存中。
3 允许获取仅实例化的bean进行赋值。
需要注意的是:spring中,只能实现set注入的循环依赖,如果在构造器中产生循环依赖,spring无法解决
传送阵