[转]spring 学习-bean创建-循环依赖-2

转载自 https://www.iflym.com/index.php/code/201208280001.html

上文中对涉及到循环引用的3个方法作了陈述。

在方法1中,对象信息对beanFactory的形式被放入singletonFactories中,这时earlySingletonObjects中肯定没有此对象(因为remove)。

在方法2中,在一定条件下(allowEarlyReference为true)的条件下,对象从singleFactories中的objectFactory中被取出来,同时remove掉,被放入earlySingletonObjects中。这时,earlySingletonObjects就持有对象信息了;当然,如果allowEarlyReference为false的情况下,且earlySingletonObjects本身就没有持有对象的情况下,肯定不会将对象从objectFactory中取出来的。这个很重要,因为后面将根据此信息进行循环引用处理。

在方法3中,对象被加入到singletonObjects中,同时singletonFactories和earlySingletonObjects中都remove掉持有的对象(不管持有与否),这就表示在之前的处理中,这只相当于一个临时容器,处理完毕之后都会remove掉。

那么,我们来看这3个方法是不是按照先后顺序被调用的呢。代码顺序如下所示:

类AbstracBeanFactory获取bean。M-1

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }               ……
}

进入getSingleton方法M-2

Object singletonObject = this.singletonObjects.get(beanName);
                try {
//首先执行getObject方法,再执行finnaly中的addSingleton方法,即上文中的方法3
                    singletonObject = singletonFactory.getObject();
                }finally {
addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }

查看singletonFactory.getObject(),即createBean(beanName, mbd, args),最终转向doCreateBean方法M-3

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
                    instanceWrapper = createBeanInstance(beanName, mbd, args);
            addSingletonFactory(beanName, new ObjectFactory() {
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

上面代码会调用方法addSingletonFactory,即上文所说的方法1。
那么方法2会在什么地方调用呢。答案在两个地点。

第一个地方,称之为调用点A,即在最开始获取bean时,会调用。

Object sharedInstance = getSingleton(beanName);

此方法最终会调用到

getSingleton(beanName, true)

这里传递了参数true。即会尝试解析singletonFactories。然而,在最开始创建对象时,singletonFactories中肯定不会持有对象信息,所以会返回null。

第二个地方,称之为调用点B,即在完成bean创建时,会有一个验证过程。即在方法M-3中,即在调用方法2之前。代码如下:

if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    if (!actualDependentBeans.isEmpty()) {
                        throw 文章开头的异常。
                    }
                }
            }

调用点B的逻辑有点多,后面的逻辑主要是作循环引用验证。注意在调用点B传递参数为false,即不会解析singletonFactories。

详细见下一篇

原文地址:https://www.cnblogs.com/Benjious/p/15183075.html