专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Spring源码三级缓存

  循环依赖
  两个或两个以上对象互相依赖对方,形成一个依赖环,例如A对象依赖B对象,B对象依赖A对象。
  当创建相互依赖的对象时,会形成死循环,例如下图无缓存中的情况。而Spring通过增加缓存,将未完全创建好的A提前暴露在缓存中,当相互依赖的对象B对属性A赋值时,可以直接从缓存中获取A,而不需要再创建A,例如下图有缓存中的情况。
  Spring的三级缓存
  Spring的三级缓存分别为:singletonObject:一级缓存,缓存中的bean是已经创建完成的,该bean经历过实例化属性填充初始化以及各种的后置处理。因此,一旦需要获取bean时,会优先寻找一级缓存publicObjectgetSingleton(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(beanName,Beannamemustnotbenull);synchronized(this。singletonObjects){。。。ObjectsingletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnull){bean创建前操作,标记当前bean正在创建beforeSingletonCreation(beanName);booleannewSingletonfalse;try{创建beansingletonObjectsingletonFactory。getObject();newSingletontrue;}catch(Exceptionex){。。。}finally{if(recordSuppressedExceptions){this。suppressedExceptionsnull;}bean创建后操作,删除当前bean正在创建afterSingletonCreation(beanName);}if(newSingleton){存入一级缓存addSingleton(beanName,singletonObject);}}returnsingletonObject;}}在bean创建完成之后,将bean加入到一级缓存中protectedvoidaddSingleton(StringbeanName,ObjectsingletonObject){synchronized(this。singletonObjects){添加一级缓存this。singletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);this。earlySingletonObjects。remove(beanName);this。registeredSingletons。add(beanName);}}复制代码earlySingletonObjects:二级缓存,该缓存跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化还没有做完,因此该bean还没创建完成,时半成品,仅仅能作为指针提前曝光,被其他bean所引用二级缓存是从三级缓存中通过getObject()方法获取的protectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){ObjectsingletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){singletonObjectthis。earlySingletonObjects。get(beanName);if(singletonObjectnullallowEarlyReference){synchronized(this。singletonObjects){ConsistentcreationofearlyreferencewithinfullsingletonlocksingletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnull){singletonObjectthis。earlySingletonObjects。get(beanName);if(singletonObjectnull){ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){三级缓存通过getObject()方法获取半成品beansingletonObjectsingletonFactory。getObject();存放二级缓存this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}}}}}}returnsingletonObject;}复制代码singletonFactories:三级缓存,在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory。getObject()获取。在实例化bean之后,如果允许循环依赖,将未创建完的bean加入到三级缓存if(earlySingletonExposure){if(logger。isTraceEnabled()){logger。trace(EagerlycachingbeanbeanNametoallowforresolvingpotentialcircularreferences);}存入三级缓存addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));}protectedvoidaddSingletonFactory(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(singletonFactory,Singletonfactorymustnotbenull);synchronized(this。singletonObjects){if(!this。singletonObjects。containsKey(beanName)){存放三级缓存this。singletonFactories。put(beanName,singletonFactory);this。earlySingletonObjects。remove(beanName);this。registeredSingletons。add(beanName);}}}复制代码三级缓存的使用
  当A和B相互依赖时,若先创建实例A,则整个调用过程为:
  其中涉及缓存和依赖相关主要过程为:开始创建实例A,标记A为正在创建protectedvoidbeforeSingletonCreation(StringbeanName){将实例A加入到singletonsCurrentlyInCreation中if(!this。inCreationCheckExclusions。contains(beanName)!this。singletonsCurrentlyInCreation。add(beanName)){thrownewBeanCurrentlyInCreationException(beanName);}}复制代码实例化A后,将未赋值和初始化的实例A加入到三级缓存singletonFactories中addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));protectedvoidaddSingletonFactory(StringbeanName,ObjectFactorylt;?singletonFactory){Assert。notNull(singletonFactory,Singletonfactorymustnotbenull);synchronized(this。singletonObjects){if(!this。singletonObjects。containsKey(beanName)){放入三级缓存this。singletonFactories。put(beanName,singletonFactory);二级缓存删除该beanthis。earlySingletonObjects。remove(beanName);this。registeredSingletons。add(beanName);}}}复制代码由于循环依赖,实例A触发实例B加载,标记B为正在创建,并在实例化B后,将未赋值和初始化的实例B加入到三级缓存singletonFactories中(同上)由于循环依赖,实例B触发实例A加载,在缓存中获取到未创建好的AprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){一级缓存中不存在A,返回nullObjectsingletonObjectthis。singletonObjects。get(beanName);A因为已经标记为正在创建,进入下面的if语句if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){二级缓存不存在A,返回nullsingletonObjectthis。earlySingletonObjects。get(beanName);允许循环依赖if(singletonObjectnullallowEarlyReference){锁定一级缓存和二级缓存,并再次检验synchronized(this。singletonObjects){singletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnull){singletonObjectthis。earlySingletonObjects。get(beanName);if(singletonObjectnull){三级缓存中存在未创建好的实例A,获取到ObjectFactory对象ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){调用getObject()方法,获取到为创建好的实例AsingletonObjectsingletonFactory。getObject();将实例A放入到二级缓存中this。earlySingletonObjects。put(beanName,singletonObject);三级缓存中删除实例Athis。singletonFactories。remove(beanName);}}}}}}returnsingletonObject;}复制代码在B创建好之后,则标记实例B创建完成,并将B加入到一级缓存中protectedvoidafterSingletonCreation(StringbeanName){将实例B从singletonsCurrentlyInCreation中删除if(!this。inCreationCheckExclusions。contains(beanName)!this。singletonsCurrentlyInCreation。remove(beanName)){thrownewIllegalStateException(SingletonbeanNameisntcurrentlyincreation);}}protectedvoidaddSingleton(StringbeanName,ObjectsingletonObject){synchronized(this。singletonObjects){将实例B放入一级缓存this。singletonObjects。put(beanName,singletonObject);三级缓存中删除Bthis。singletonFactories。remove(beanName);二级缓存中删除Bthis。earlySingletonObjects。remove(beanName);this。registeredSingletons。add(beanName);}}复制代码在A创建好之后,则标记实例A创建完成,并将A加入到一级缓存中AOP和三级缓存不涉及AOP
  实例加入到三级缓存,并从三级缓存中获取实例过程如下:添加到三级缓存addSingletonFactory(beanName,()getEarlyBeanReference(beanName,mbd,bean));使用三级缓存ObjectFactorylt;?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){singletonObjectsingletonFactory。getObject();this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}复制代码
  从三级缓存获取到的bean,是经过getEarlyBeanReference()作用之后返回的bean,在不涉及AOP时,没有类覆盖实现getEarlyBeanReference()方法,使用getEarlyBeanReference()的默认实现,因此返回的bean就是实例化后的原始bean。defaultObjectgetEarlyBeanReference(Objectbean,StringbeanName)throwsBeansException{returnbean;}复制代码涉及AOP
  当涉及到AOP时,AbstractAutoProxyCreator实现了getEarlyBeanReference()方法,返回的bean是经过AOP代理的bean。publicObjectgetEarlyBeanReference(Objectbean,StringbeanName){ObjectcacheKeygetCacheKey(bean。getClass(),beanName);this。earlyProxyReferences。put(cacheKey,bean);创建AOP代理returnwrapIfNecessary(bean,beanName,cacheKey);}复制代码
  不涉及循环依赖时,bean的AOP代理是在实例化,赋值,初始化之后创建的。而涉及循环依赖时,三级缓存中保存的是实例化但未赋值,初始化之后的bean,当通过三级缓存获取实例时,则会提前创建AOP代理:非循环依赖,在实例化,赋值,初始化之后创建AOP代理循环依赖,在实例化,未赋值,初始化之后创建AOP代理(提前创建代理)
  对于在缓存中提前创建好代理的实例,当赋值,初始化之后,运行至bean的后置处理逻辑,即AbstractAutoProxyCreator的postProcessAfterInitialization方法(正常创建AOP代理逻辑)时,则不会再次创建AOP代理,返回的是不经代理的bean。AbstractAutoProxyCreator的后置处理逻辑publicObjectpostProcessAfterInitialization(NullableObjectbean,StringbeanName){if(bean!null){由于提前创建了代理并且有缓存,则不再返回代理ObjectcacheKeygetCacheKey(bean。getClass(),beanName);if(this。earlyProxyReferences。remove(cacheKey)!bean){returnwrapIfNecessary(bean,beanName,cacheKey);}}returnbean;}复制代码
  再返回赋值和初始化bean的逻辑中,exposedObject作为最终的返回结果,在使用到AOP时,最终返回的都是代理bean原始beanObjectexposedObjectbean;try{实例赋值populateBean(beanName,mbd,instanceWrapper);实例初始化(初始化后调用bean的后置处理逻辑,即创建AOP代理)(1)非循环依赖,未提前创建代理,initializeBean返回的是代理bean(2)循环依赖,提前创建代理,initializeBean返回的是原始beanexposedObjectinitializeBean(beanName,exposedObject,mbd);}if(earlySingletonExposure){当allowEarlyReferencefalse时,只能从一级二级缓存中获取实例(1)未提前创建代理时,实例在三级缓存中,getSingleton返回代理null(2)提前创建代理时,实例在二级缓存中,返回代理beanObjectearlySingletonReferencegetSingleton(beanName,false);if(earlySingletonReference!null){提前创建代理,代理bean在缓存中,所以下面相等if(exposedObjectbean){将代理bean赋值给exposedObjectexposedObjectearlySingletonReference;}。。。}}
  作者:重新做人
  链接:https:juejin。cnpost7190744581351473207

主流手机厂商代表作盘点有的开启全面屏时代,有的500天不卡顿对于普通消费者来说,手机那些繁复的性能参数,我们未必能全部看得懂,但是只要手机好看好用,我们就足够了。而且很多用户选择新机的时候,都喜欢跟风,又或者是选择一直在市场中立足很久的系列vivo火力不停歇,12G256G骁龙8,7英寸2K大屏手机跌至4749元vivo已经官宣,新旗舰机将首发天玑9200旗舰芯片,具体机型为vivoX90Pro,最近很多人把目光都集中在了这款手机上,相关的配置外观和发布时间曝光,据说11月22日推出。不过1。7亿!欧足坛变了,哈兰德追赶梅西,3新星爆发,曼城皇马笑了五大联赛开赛至今,有很多球员的发挥都给球迷留下非常深刻的印象,尤其是很多青年才俊的发挥更是不禁令人感叹长江后浪推前浪。在最新一期的德转身价排行中,排名前十的均是20出头的年轻球员,跳水皇后郭晶晶带一身伤病下嫁千亿豪门,生下3胎被宠上天她是下嫁豪门的跳水女皇,在役14年获得31个世界冠军。而这背后却是用一身伤病换来的。因为长时间在水中她患有严重的关节炎,双眼视力更是低到只有0。2。她的头发因为游泳池中消毒水的侵害江苏,凭什么是第一?这个国庆黄金周,频频被江苏省刷屏。旅游收入稳占第一宝座,比第二名领先了100多个亿高速服务区被网友赞叹说一旦去了,就不想再回来服务区的装修精致到让网友用刘姥姥进大观园来形容自己无锡2022河北省民营企业100强排行榜中商情报网讯近日,河北省工商联发布了2022河北省民营企业100强榜单。榜单显示,营业收入总额达30056。90亿元,较上年增长2990。45亿元,增长率11。05入围门槛为38。新疆好玩的地方你去过几个?新疆好玩的地方有喀纳斯风景区天池景区可可托海那拉提风景区赛里木湖喀什古城世界魔鬼城景区葡萄沟风景区泽普金胡杨国际大巴扎帕米尔高原等,都是新疆好玩的地方,也都代表着新疆景点的特色,值新疆白哈巴西北第一村,可以治愈心灵的童话般的村庄在祖国的最西北,有一个静谧的童话村庄新疆白哈巴村。它是西北第一村,位于祖国雄鸡版图的尾巴尖上,与哈萨克斯坦仅隔着一条河,春夏之交水草丰美的时候,哈萨克斯坦的牧民还会跨越河谷来放牧。世界第一!投165亿建深圳湾垂直城市超高层第一高楼近一个月前的2022年10月13日上午,随着第1433根工程桩施工完毕,深圳湾超级总部基地C塔及相邻地块工程桩基全面完成,标志着这个总投资达到165亿元的深圳最高楼将进入地面以上施多面尼斯很多人说,法国是欧洲最浪漫的地方,巴黎则是法式浪漫的代表。但其实,很多法国人并不认同这个说法。他们认为,巴黎太喧闹,有国际大都市的通病,尼斯才是真正的天堂。尼斯位于法国东南部的地中终于有人敢露了!柳岩红毯再现性感线,连倪妮都被抢风头hi大家好连着热闹了大半个月,看了三四场红毯,昨儿个好多网友还是被金鸡奖闭幕式红毯的神仙打架给惊呆了。用一句话总结,就是有人一直美丽,有人用力过猛,小编在这再加一句会露的性感最不一
火力全开!贵州各地节后复工竞相争好局春节假期刚过,员工返回工作岗位,企业迎来复工复产高峰。走进贵州多家企业和项目建设现场,所到之处,火力全开。2月6日,工人在岑巩经济开发区贵州汉豪电气有限公司生产车间作业。唐鹏摄新春突然爆火蔓延的深度和广度已超乎想象!这个新的生意经被淘金者瞄准,有人零成本月入数十万每经记者文巧每经编辑程鹏,高涵ChatGPT掀起的科技巨浪蔓延的深度和广度已经超出了想象。近日,黑马产品ChatGPT轮番登上热搜,引发网友热议。在去年11月30日发布后的5天时间城市建成区测量丰都丰都,古称酆都,以鬼城著称。其地处重庆市中部,东临石柱,西接涪陵,北挨忠县,南靠武隆,西北与东南分别与垫江彭水交接。丰都在重庆的位置丰都县下辖2街23镇5乡,幅员面积2901平方千家在沈阳征文南雁北飞!我把家安在沈阳今日头条版权图南雁北飞!我把家安在沈阳陈丽群2019年3月,我携着一个小皮箱,乘坐飞机飞越1800多公里到达沈阳。当年5月,我买下一间小房,将家安在了沈阳。从此,我的生活展开了全新瑞雪中的张家川关山段如诗如画新天水讯据张家川县融媒体中心消息一场春雪降临张家川县,将巍峨雄壮的关山装扮得银装素裹气象万千,远远望去,犹如一幅水墨画展现于世人眼前。沿S221省道而行,远山丛林在白雪掩映下,千树欧洲行(十三)因为我们有坐小船游威尼斯这个项目,所以先从圣马克广场乘坐游船巴士到达其中一个贡多拉小船的放置地,然后再乘坐贡多拉小船畅游威尼斯。小船可乘坐六人,我俩和其中一家四口坐在一起,当时意大浅浅说说孔庙建筑里的勾心和斗角今年的曲阜之行与以前走马观花的游玩又有不同,三年的疫情和年龄的增长让我整个人的心态都变了进了孔庙能够细心聆听导游的讲解,心思专注在自己感兴趣的名人故事和历史建筑上,对景区的其他东西采风春天里的中原冶炼邂逅冰挂,不负相遇乍暖还寒时,在中原冶炼厂区遇见绝美的冰挂。冰化为水,冰水交融,水是冰的语言,水流顺势流下,在廊檐下凝结成壮观的冰挂,晶莹剔透,造型各异。从廊檐下仰观,在阳光的照射下剔透的冰挂和清澈厦门翔安妙高山千株樱花树盛开,自驾导航佛国寺即可2月8日,我自驾前往厦门翔安妙高山寻找美丽的樱花。开车到了劳光水库,看到都是山路,车辆稀少,不敢再前进,电话咨询同事后,说导航到佛国寺即可。一路上山,到了佛国寺,千株樱花在茶园中盛情人节浪漫游嘉义八景点等你来来源台海网电影消失的情人节取景美地白水湖寿岛(台媒图)山景海景湖景茶园星空,一应俱全据华夏经纬网2月8日报道2月14日情人节临近,嘉义县文化观光局精选8处约会必访景点,山景海景湖景每张都是壁纸!这样的尧山(石人山)你见过没?河南日报客户端记者张建新河南日报社全媒体记者王冰珂通讯员郭东伟漫山的古木清澈的溪流飘逸的云海远处的奇峰一年四季的尧山(石人山),都美不胜收。尧山风景名胜区地处伏牛山东麓平顶山市鲁山
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网