栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

对spring解决循环依赖的理解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

对spring解决循环依赖的理解

首先我感觉不能抛开问题去理解一个东西,所以这里还是再问一句:

什么是循环依赖?

循环依赖有几种,A->A ,A->B->A,A->B->C->B->A等等,由于没有更进一步研究,我说下这里可能涉及的一些更多的问题:

                                1.不同依赖形式可能导致处理方式不一样

                                2.不同的依赖注入方式可能导致spring的处理结果不一样

java bean,spring bean?

        java bean 就是java对象,spring bean由spring创建封装并管理对象,比如一个重要差别:如果ioc容器注入的bean使用了AOP去增强某个方法,那么在用注入对象调用该方法时,实际是调用了代理对象的方法。

sping中bean的生命周期?

如果先要理解spring如何解决循环依赖,先需要知道spring中bean的生命周期。

这里简单写四个相对重要的步骤(实际过程还会更复杂一些,例如bean的前后置处理器,aware获取bean在容器中的属性等等):

                 bean的创建 ...--> bean属性赋值 ...--> bean的初始化...-->(如果有AOP)等等

bean的创建:主要是生成属性未赋值对象。

bean的属性赋值:给bean的属性赋值,例如bean中依赖的bean。

bean的初始化: 执行一系列操作。

(如果使用AOP):使用动态代理去增强方法。

如何解决循环依赖?

首先要知道三级缓存:

        一级:存放完整的bean,可以直接被使用。

        二级:存放不完整的bean,未完成属性赋值。

        三级:存放bean的创建工厂

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        //1级缓存 用于存放 已经属性赋值 初始化后的 单列BEAN
        private final Map singletonObjects = new ConcurrentHashMap<>(256);
        //2级缓存 用于存在已经实例化,还未做代理属性赋值操作的 单例
        private final Map earlySingletonObjects = new HashMap<>(16);
        //3级缓存 存储单例BEAN的工厂
        private final Map> singletonFactories = new HashMap<>(16);
        //已经注册的单例池里的beanName
        private final Set registeredSingletons = new linkedHashSet<>(256);
        //正在创建中的beanName
        private final Set singletonsCurrentlyInCreation =
                Collections.newSetFromMap(new ConcurrentHashMap<>(16));
        //缓存查找bean  如果1级没有,从2级获取,也没有,从3级创建放入2级
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName); //1级
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName); //2级
                    if (singletonObject == null && allowEarlyReference) {
                        //3级缓存  在doCreateBean中创建了bean的实例后,封装ObjectFactory放入缓存的
                        ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            //创建未赋值的bean
                            singletonObject = singletonFactory.getObject();
                            //放入到二级缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            //从三级缓存删除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return singletonObject;
        }   
    }

来源于Spring三级缓存 - 简书

 三级缓存思路

 由于bean的创建过程是:属性未赋值...->属性赋值...->完整bean

所以我的思路推导过程如下(尚未严格验证):

       需要 属性未赋值A,一二级缓存没有 属性未赋值A,从三级缓存中拿到 A工厂 去创建 属性未赋值A,放入二级缓存,删掉三级缓存中的 A工厂。

       进行 A的属性赋值,一级缓存没有,二级缓存有,假设 属性未赋值A 依赖 B,B又依赖A,,因二级缓存有属性未赋值A(也是A),所以使之能创建 假完整B ,然后将 假完整B 存入一级缓存。

        属性未赋值A 得到 假完整B,完成属性赋值,存入一级缓存,删掉二级缓存中的 A。此时B真正完整。

还有几个问题,依赖注入的方式有哪几种,有什么区别?

spring的三级缓存能够解决哪几种?

如果不是单例bean是怎么处理的?

        

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/755388.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号