Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
962 views
in Technique[技术] by (71.8m points)

Spring的循环依赖中的三级缓存

如题,我所了解的循环依赖是通过三个哈希表来分别存储已初始化,已实例化但还未注入属性和初始化和进入实例化阶段的bean来解决的。

    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    
    //存放已实例化,但尚未填充属性和初始化的bean,我们称这类bean为早期引用。该二级缓存用于解决循环依赖
    private final Map<String, Object> earlySingletonObjects = new HashMap(16);
    
    //存放进入实例化阶段的Bean,主要作用是提前暴露这些bean
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);

我对第三个哈希表存储的键值对有点不理解,它存储的键是beanName,那他存储的value是什么呢?
我在看了一下相关源码:

//doCreateBean方法的一部分
 if (earlySingletonExposure) {
            //...
            //3.将创建完的bean添加到三级缓存
             this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }
//如果bean不是AOP代理,则本方法直接返回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();
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }
  protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                //3-2将beanName-singletonFactory工厂作为映射添加到三级缓存里
                this.singletonFactories.put(beanName, singletonFactory);
                //3-3从二级缓存里移除beanName
                this.earlySingletonObjects.remove(beanName);
                //3-4在registeredSingletons里注册beanName
                this.registeredSingletons.add(beanName);
            }
        }
    }

觉得三级缓存存储的value值是RootBeanDefinition,我对这个类的理解是它存储的是Bean定义的信息,但它也是一个ObjectFactory?
不知道这么理解是否正确,希望有人指点一下?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

代码中写的是一个lamda表达式,即ObjectFactory

//3.将创建完的bean添加到三级缓存
             this.addSingletonFactory(beanName, () -> {
               ** return this.getEarlyBeanReference(beanName, mbd, bean);**
            });

1.循环引用时,会调用三级缓存getEarlyBeanReference:

//如果bean不是AOP代理,则本方法直接返回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();
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

2.可以看到mbd只用来判断是否需要进行BeanPostProcessor操作,但是方法最终返回的是bean。
所以说三级缓存真正想保存的其实是bean对象。但是由于Aop存在,有时需要返回代理对象而不是原始bean,所以会调用ibp.getEarlyBeanReference获取代理后的对象


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...