关于java:spring-循环依赖问题研究

7次阅读

共计 2742 个字符,预计需要花费 7 分钟才能阅读完成。

CASE:“A 的某个 field 或者 setter 依赖了 B 的实例对象,同时 B 的某个 field 或者 setter 依赖了 A 的实例对象”。
剖析:
1.A 进行 create 流程,发现自己依赖 B, 此时 B 更没有走 create 流程。
doCreateBean() 中

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));

isSingletonCurrentlyInCreation(beanName) 的具体实现是:

protected void beforeSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
        }
    }

那么它的调用机会又是什么时候呢?
DefaultSingletonBeanRegistry.getSingleton();
AbstractBeanFactory.doGetBean() 中也就是 AbstractBeanFactory.getBean() 调用了下面这个办法.
在这里还有一个调用链路就是:
AbstractApplicationContext.finishBeanFactoryInitialization(beanFactory)->

    beanFactory.preInstantiateSingletons()->AbstractBeanFactory.getBean().

在这里,我目前先探讨这两个次要的调用链路,其余的当前再说。
咱们接着剖析,如果判断出循环援用,则执行 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))。
看一下具体实现:

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);
            }
        }
    }

见到了相熟的 singletonFactories,是不是很兴奋呢;此时,A 将本人放入到 singletonFactories 中。
2. 发现自己依赖对象 B,此时就尝试去 get(B),发现 B 还没有被 create,所以 B 走 create 流程。
3.B 初始化时时候发现自己依赖 A,尝试 get(A),从 singletonObjects(一级缓存) 中取,发现没有(此时 A 还没有初始化实现),earlySingletonObjects(二级缓存)中也没有,最初从 singletonFactories(三级缓存)中取,因为在 1 中 A 曾经寄存在 singletonFactories 外面了,所以 B 能够拿到 A(尽管是个半成品)。
4. 此时,B 能够顺利完成初始化,并将本人放在 singletonObjects 中。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction" +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean'" + beanName + "'");
                }
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                if (newSingleton) {
                    // 增加到 singletonObjects 中
                    addSingleton(beanName, singletonObject);
                }
}

上面看,具体实现:

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);
        }
    }

5. 此时返回 A 中,A 此时能拿到 B, 最终 A 也实现了初始化,进去了一级缓存 singletonObjects 中。

正文完
 0