美文网首页spring
spring循环引用

spring循环引用

作者: loveFXX | 来源:发表于2019-10-31 15:38 被阅读0次

    spring在默认单例的情况下是支持循环引用的
    代码体现在AbstractAutowireCapableBeanFactory#doCreateBean方法中
    (boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    isSingletonCurrentlyInCreation(beanName));)
    isSingleton是否是单例 ,allowCircularReferences 默认是true,可以通过api关闭循环依赖。
    通过AbstractAutowireCapableBeanFactory#setAllowCircularReferences(false)方法关闭

        public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
            this();
            register(annotatedClasses);
            setAllowCircularReferences( false );
            refresh();
        }
    

    循环依赖示例代码

    package com.cycle;
    @Component
    public class A {
        @Autowired
        B b;
        int ac=5;
    }
    
    package com.cycle;
    @Component
    public class B {
        @Autowired
        A a;
        int bc=3;
    }
    

    debug过程

    根据beanName=a,获取getBean(a)


    getbean.png

    调用到doGetBean(a)方法


    doGetBean.png
    进入getSingleton方法
    getSingleton.png

    首先设置此时正在创建a,放入集合。调用getObject进入lamdba表达式createBean


    getObject.png
    createBean调用到doCreateBean
    createBean.png
    创建bean
    经过推断构造方法,缓存注解信息,暴露对象工厂,到属性填充
    doCreateBean.png
    属性填充
    populateBean.png

    调用后置处理器进行属性填充(模版方法)
    AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues


    postProcessPropertyValues.png
    注入
    inject.png
    elementinject.png
    resolveDependency.png
    doResolveDependency.png
    resolveCandidate.png
    BeanFactorygetBean.png
    getBeanB.png
    所谓循环依赖,就是A含有B的属性,B含有A的属性。
    从debug大概流程:getBean(beanName)说起,首先需要创建A,A需要填充属性B,注入B需要从BeanFactory(Bean工厂)查询B是否存在,现在肯定不存在则继续创建B,B需要填充属性A,再次从bean工厂查询,到这里则A能查询到。(此时将会经过spring后置处理器全部过程)
    getSingletona.png
    singletonFactorygetObject.png
    此时,A正在创建isSingletonCurrentlyInCreation(a)返回true,将会从singletonFactories得到。得到之后放到earlySingletonObjects中,并把singletonFactories中移除,并一直返回并进行属性set 。B注入从singletonFactories查询到的A对象
    getEarlyBeanReference.png
    BPPgetEarlyReference.png
    public boolean isSingletonCurrentlyInCreation(String beanName) {
            return this.singletonsCurrentlyInCreation.contains(beanName);
        }
    
    fieldset.png
    fieldsetAfter.png

    A注入B之后,经过B的生命周期,返回得到带有A属性的B对象。B注入到A之中,最终效果如下图


    AfieldsetB.png
    再经过A 的其他生命周期过程。完成循环依赖过程

    方法参考

    singletonsCurrentlyInCreation添加正在被创建bean

    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                    return createBean(beanName, mbd, args);
                    }
                });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
        }
    

    添加单例工厂,提前暴露工厂

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

    getSingleton()方法
    bean:首先得是一个对象,然后这个对象需要经历一系列的bean生命周期(bean后置处理器处理过程)

       public Object getSingleton(String beanName) {
            return getSingleton(beanName, true);
        }
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return singletonObject;
        }
    

    AbstractAutowireCapableBeanFactory#doCreateBean源码

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable 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.getWrappedInstance();
            Class<?> beanType = instanceWrapper.getWrappedClass();
            if (beanType != NullBean.class) {
                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) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Post-processing of merged bean definition failed", ex);
                    }
                    mbd.postProcessed = true;
                }
            }
    
            // Eagerly cache singletons to be able to resolve circular references
            // even when triggered by lifecycle interfaces like BeanFactoryAware.
                   //解决循环引用的地方
            boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                    isSingletonCurrentlyInCreation(beanName));
            if (earlySingletonExposure) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Eagerly caching bean '" + beanName +
                            "' to allow for resolving potential circular references");
                }
                //第四次 后置处理器 暴露对象到singlentonfactories集合中 解决循环依赖问题
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                //填充属性
                //第五次 是否需要填充属性
                //第六次 填充属性
                populateBean(beanName, mbd, instanceWrapper);
    
                //初始化bean
                //第七次
                //第八次  aop
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
            catch (Throwable ex) {
                if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                    throw (BeanCreationException) ex;
                }
                else {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "Initialization of bean failed", 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<>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
                        if (!actualDependentBeans.isEmpty()) {
                            throw new BeanCurrentlyInCreationException(beanName,
                                    "Bean with name '" + beanName + "' has been injected into other beans [" +
                                    StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                    "] in its raw version as part of a circular reference, but has eventually been " +
                                    "wrapped. This means that said other beans do not use the final version of the " +
                                    "bean. This is often the result of over-eager type matching - consider using " +
                                    "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                    }
                }
            }
    
            // Register bean as disposable.
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
            }
    
            return exposedObject;
        }
    

    AbstractAutoProxyCreator#getEarlyBeanReference 处理代理类

        public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            this.earlyProxyReferences.put(cacheKey, bean);
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    

    总结:

    getSingleton()方法是解决循环依赖的关键。
    有三个缓存集合
    1、singletonObjects
    bean放到里面,经历完整生命周期
    2、singletonFactories
    存放生成对象的工厂 是一个表达式 (包含对象) 对象需要改变,改变之后放到3
    如果依赖的对象需要实现aop,则需要在这里存一个能够完成生成代理类的工厂。如果不在这里代理则注入的对象没有代理功能
    参考AbstractAutoProxyCreator#getEarlyBeanReference方法
    3、earlySingletonObjects
    工厂生成的对象,此时生命周期没有走完。如果还有其他地方引用就不需要再通过2再次生成

    关键点:
    1、singletonsCurrentlyInCreation集合
    当创建bean时,将首先DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)表达式中
    beforeSingletonCreation(beanName)加进去
    2、addSingletonFactory方法
    通过方法addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));添加到singletonFactories。当再次调用时ObjectFactory的实现类AbstractAutowireCapableBeanFactory$lambda的getObject()方法最终调用getEarlyBeanReference方法,返回bean实例

    相关文章

      网友评论

        本文标题:spring循环引用

        本文链接:https://www.haomeiwen.com/subject/kbkovctx.html