Spring源码分析-bean创建(循环依赖)

Posted cao_xiaobo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码分析-bean创建(循环依赖)相关的知识,希望对你有一定的参考价值。

 

一、循环依赖产生的原因
 
A依赖B,B又依赖A
@Component
class A {
    @Autowired
    B b;
}
@Component
class B {
    @Autowired
    A a;
}
A类Bean创建过程:
  • 先实例化A,(一般都是)通过无参构造完成实例化;
  • A属性注入,发现A依赖B,准备B类Bean的创建;
  • 实例化B,通过无参构造完成实例化;
  • B属性注入,发现B依赖A,准备A类Bean的创建;
依次类推,就会产生一个死循环!好在spring已经为我们解决了这一问题。那么Spring中如何解决这个循环依赖的呢?
Spring解决循环依赖的核心方法有两个,一个是doGetBean中调用 getSingleton 方法,另一个是doCreateBean中调用addSingletonFactory  方法

 

二、源码分析

 
准备调试
(1)在DefaultListableBeanFactory.preInstantiateSingletons() 方法上进行断点调试,for循环断点过滤(beanName.equals("a") || beanName.equals("b"))
(2)在DefaultListableBeanFactory(AbstractBeanFactory).doGetBean方法上断点调试;第1次获取A的bean;第2次获取B的bean;第3次获取A的bean
下面是方法栈的信息:
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton        从singletonFactories拿到了这个A的bean
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean
DefaultListableBeanFactory(AbstractBeanFactory).getBean                        6.获取属性A的bean
DependencyDescriptor.resolveCandidate
DefaultListableBeanFactory.doResolveDependency
DefaultListableBeanFactory.resolveDependency
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject            5.对B中的带注解Autowired属性A注入
InjectionMetadata.inject
AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean    4.创建B的bean(先实例化)
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean
AbstractBeanFactory$1.getObject()
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>)
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean                    3.获取属性B的bean
DefaultListableBeanFactory(AbstractBeanFactory).getBean                        
DependencyDescriptor.resolveCandidate
DefaultListableBeanFactory.doResolveDependency
DefaultListableBeanFactory.resolveDependency
AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject            2.对A中的带注解Autowired属性B注入
InjectionMetadata.inject
AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).populateBean
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean    1.创建A的bean(先实例化)
DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean    
AbstractBeanFactory$1.getObject()
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>)
DefaultListableBeanFactory(AbstractBeanFactory).doGetBean 断点调试             首次获取A的bean

 

通过方法栈,我画出了一个方法调用流程图
 
执行流程:
  1. doGetBean 首次获取A的bean,通过getSingleton方法获取A的bean,如果不存在,createBean;
  2. doCreateBean 开始创建A的bean,先实例化,接着判断是否需要提前暴露bean,这一步就提前暴露A的bean了,即向singletonFactories添加了A的bean操作,再调用populateBean方法进行属性注入;
  3. inject 对A中的带注解Autowired属性/方法 对B进行注入,最终又会调用getBean来获取B的bean;
  4. doGetBean 获取B的bean,此时,B因为是首次,所以又会对B的bean进行createBean操作;
  5. doCreateBean 开始创建B的bean,同样先实例化,判断是否需要提前暴露bean,再进行属性注入
  6. inject 对B中的带注解Autowired属性/方法 对A进行注入,最终又会调用getBean来获取A的bean;
  7. doGetBean 再次获取A的bean,这时候因为前面已经提前暴露过,所以A的Bean可以获取得到;
  8. inject 通过反射完成B的属性注入
  9. doCreateBean 完成B的bean创建
  10. inject 通过反射完成A的属性注入
  11. doCreateBean 完成A的bean创建
  12. 至此A的bean和B的bean都已经创建好了,下次轮到B来getBean时直接可以获取到。
 
(1)上面整体流程是这样的,但是在执行第7步的时候,是怎么获取到A的Bean的?下面我们来分析一下:
当第3次调用doGetBean方法时,也就是第2次获取A的bean时,当执行到 Object sharedInstance = getSingleton(beanName); 时,返回的不再是null了。
我们再来看一下getSingleton方法的功能:  
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    // 关键点1,isSingletonCurrentlyInCreation方法
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 关键点2,singletonFactories单例工厂对象
                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);
}
  • isSingletonCurrentlyInCreation,第1次调用获取A的bean的时候和第2次调用获取B的bean的时候返回都是false
  • singletonFactories,第1次调用获取A的bean的时候值为null,第一次调用获取B的bean的时候,里面就包含A的信息...
(2)singletonFactories 这个对象是什么鬼?
从上述代码上可以看出singletonFactories是一个临时存放bean实例的工厂池,当拿到了bean只后就会把相就的bean从这个临时的工厂池删除掉。
那这个A的这个bean实例是什么时候存放进去的?
当执行addSingletonFactory方法时,会向singletonFactories中设值
在doCreateBean方法bean实例化之后,会执行相关的addSingletonFactory 方法

 

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                // 抛出异常...
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // ********************** singletonFactories 设值的关键部分 START **********************
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                      isSingletonCurrentlyInCreation(beanName));
    // isSingletonCurrentlyInCreation也是一个关键方法,与getSingleton方法相呼应
    if (earlySingletonExposure) {
        
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }
    // ********************** singletonFactories 设值的关键部分 END **********************
    
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    catch (Throwable ex) {
        // 抛出异常。。。
    }

    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()) {
                    // 抛出异常。。。
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    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)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

 

总结:当循环依赖存在的时候,会一直循环调用doGetBean方法(ABABAB)...,Spring为我们解决了这一问题,使得doGetBean方法为ABA就结束了。

 

以上是关于Spring源码分析-bean创建(循环依赖)的主要内容,如果未能解决你的问题,请参考以下文章

源码分析:Spring如何解决单例Bean的循环依赖?

源码分析:Spring如何解决单例Bean的循环依赖?

Spring 源码分析--bean的加载详细分析

Spring源码分析系列-循环依赖和三级缓存

Spring源码分析系列-循环依赖和三级缓存

Spring源码分析系列-循环依赖和三级缓存