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就结束了。

  • 相关阅读:
    Checking Types Against the Real World in TypeScript
    nexus pip proxy config
    go.rice 强大灵活的golang 静态资源嵌入包
    几个golang 静态资源嵌入包
    rpm 子包创建学习
    Rpm Creating Subpackages
    ava 类似jest snapshot 功能试用
    ava js 测试框架基本试用
    The Architectural Principles Behind Vrbo’s GraphQL Implementation
    graphql-compose graphql schema 生成工具集
  • 原文地址:https://www.cnblogs.com/caoxb/p/12862940.html
Copyright © 2011-2022 走看看