美文网首页
spring循环依赖的解决方案

spring循环依赖的解决方案

作者: 丹青水 | 来源:发表于2018-08-03 18:13 被阅读0次

    spring循环依赖的解决方案

    Spring IOC循环依赖解决方案分析

    这里Spring主要用了三层缓存来完成对循环依赖的实现。

    下面的属性来源于DefaultSingletonBeanRegistry类

        /** Cache of singleton objects: bean name --> bean instance */
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
    
        /** Cache of singleton factories: bean name --> ObjectFactory */
        private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
    
        /** Cache of early singleton objects: bean name --> bean instance */
        private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    

    当获取一个实例对象的时候,会调用此方法

        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    

    先从singletonObjects 找,如果找不到会从earlySingletonObjects中查询,再找不到去singletonFactories 中去查询,如果找到的话会放在earlySingletonObjects中,那么问题来了,singletonFactories的对象是什么时候放进去的。

    研究Spring构造类实例的时候,通过AbstractAutowireCapableBeanFactory的doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)方法中调用addSingletonFactory方法将A类曝光到singletonFactories中。

        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);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }
        }
    
    

    Spring注入一个类的大体步骤分为两部分,一是先完成对类的构造工作,二是会对类的属性进行设置和填充
    那么关于的单例的类实例之间的互相引用的问题就清晰了

    假设A对象有个属性B 则在A初始化的时候,构造完成之后就放在了singletonFactories中,当发现去set属性的时候发现B没有初始化,于是接着初始化B,设置属性的时候在缓存中都可以拿到各自对象的引用,所以不会有循环依赖的报错

    相关文章

      网友评论

          本文标题:spring循环依赖的解决方案

          本文链接:https://www.haomeiwen.com/subject/areuvftx.html