zoukankan      html  css  js  c++  java
  • 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就结束了。

  • 相关阅读:
    Codeforces 101487E
    算法笔记--2-sat
    算法笔记--图的存储之链式前向星
    算法笔记--强连通分量分解
    Uva 11995 I Can Guess the Data Structure!
    算法笔记--米勒-罗宾素数测试
    HDU 5183 Negative and Positive (NP)
    算法笔记--快读(输入外挂)模板
    POJ 3258 River Hopscotch
    HDU 2289 Cup
  • 原文地址:https://www.cnblogs.com/caoxb/p/12862940.html
Copyright © 2011-2022 走看看