您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

Spring容器处理循环依赖的原理 《免费源码》

  • 时间:2022-07-15 00:42 编辑: 来源: 阅读:304
  • 扫一扫,手机访问
摘要:Spring容器处理循环依赖的原理 《免费源码》
推荐阅读:这套Github上的40K+star学习笔记,可以帮助你95%以上的Java面试。毫不夸张的说,这本SpringBoot学习指南可以处理你遇到的98%的问题。跪下!千呼万唤始出来的这套《SQL神之路》PDF终于开源了。最近看了源码,研究如何处理如下类似配置的循环依赖。1 & ltbean id = " a " class = " com . project . demo . a " scope = " singleton " & gt;2 & ltproperty name = " b " ref = " b "/& gt;3 & lt/bean & gt;4 & ltbean id = " b " class = " com . project . demo . b " scope = " singleton " & gt;5 & ltproperty name = " a " ref = " a "/& gt;6 & lt/bean & gt;注:1。Spring容器处理循环依赖的配置类必须得到singleton模式scope="singleton "的支持。如果是scope="prototype ",就不能处理循环依赖。 2.Spring容器主要依靠三级缓存机制来处理循环依赖。2.1一级缓存使用的Map:private final Map < String,Object & gtsingleton objects = new concurrent hashmap(256);2.2 L2缓存使用的映射:私有最终映射< String,Object & gtearlySingletonObjects = new HashMap(16);2.3 L3缓存使用的映射:私有最终映射< String,ObjectFactory & lt?& gt& gtsingleton factories = new HashMap(16);3.Spring容器处理循环依赖的简明概述。主要有四种处理方法:获取对象getSingleton(),创建对象(实例化)doCreateBean(),填充属性(初始化)populateBean(),返回对象addSingleton()。系统开始获取配置文件后,依次读取并加载程序。所以在上面的配置文件代码中,先实例化对象A,然后初始化对象A添加属性B,再实例化对象B,最后初始化对象B添加属性A,然后在代码执行的过程中,先调用getSingleton()方法,我们检查源代码@ nullable公共对象get singleton(string bean name){//并调用下面的重载方法return this . get singleton(bean name,true);} @可空保护对象get singleton (string beanname,boolean allowearlyreference){//首先从一级缓存中获取对象A的实例,objectsingletonobject = this . singletonobjects . get(beanname);//如果无法从一级缓存中获取A对象,请检查是否正在创建该对象。如果正在创建,则输入If循环(singleton object = = null & & amp这个。issingletoncurrentcreation(bean name)){ synchronized(this。singleton objects){//获取对象singletonObject = this。来自L2缓存的earlysingletoobjects . get(bean name );//如果无法从L2缓存中获取对象,那么肯定会进入下面的if方法,因为allowEarlyReference为true if(singleton object = = null & & amp;allowarelyreference){//获取对象objectfactory <?& gtsingleton factory =(object factory)this . singleton factories . get(bean name);if (singletonFactory!= null) {//如果获得对象,则将三级缓存中的对象放入二级缓存,删除三级缓存中的对象= singleton object = singleton factory . getobject();this . earlysingletonobjects . put(bean name,singleton object);this . singleton factories . remove(bean name);} } } }返回singletonObject}从三方的源代码中发现,如果第一次获得A,第9行的if语句为false,会直接放回null。此时返回到创建对象doCreateBean()的方法,通过反射生成A对象,对象在三级缓存中。对象生成后,需要填充A对象的属性:1保护对象DocreateBean (string beanname,rootbeandefinition MBD,@ NullableObject [] args)抛出BeancreationException { 2//省略多行代码基本就是调用各种方法,通过反射创建对象3 try {4 // a对象创建完成,调用属性填充方法,A的属性用5this填充。填充bean (beanname,mbd,instance wrapper);6 exposedObject = this . initialize bean(bean name,exposed object,mbd);7 } catch(Throwable var 18){ 8 if(var 18 instance of BeanCreationException & amp;& ampbean name . equals(((BeanCreationException)var 18)。get beanname())){ 9 throw(BeanCreationException)var 18;10 } 11 12 throw new BeanCreationException(mbd . getresourcedescription(),beanName,“bean初始化失败”,var 18);13 } 14 15 if(earlySingletonExposure){ 16 Object earlySingletonReference = this . get singleton(bean name,false);17 if (earlySingletonReference!= null) {18 //省略多行代码19 }20 }22 //省略多行代码23}先在上面的代码doCreateBean()方法中创建A对象,创建后会调用this.populatebean (beanname,mbd,instancewrapper)方法填充A的属性,此时所有的 在对象A的初始化过程中,对象B也被实例化和初始化。在B初始化的过程中,A从三级缓存移到二级缓存。B初始化后会继续向下执行,执行到addSingleton()。检查源代码保护的void add singleton(string bean name,Object singleton Object){ synchronized(this。singleton objects){//将B添加到一级缓存this。singleton objects.put (beanname,singleton object);//从L3缓存中删除B的this . singleton factors . remove(bean name );//从L2缓存中删除B(B在L2缓存中不存在,即被删除为空)this . earlysingletoobjects . remove(bean name);this . registered singletons . add(bean name);}}从上面的代码可以看出,在创建和初始化之后,B会直接从三级缓存放到一级缓存中,三级缓存中的数据会被删除。 B所有工作完成后,返回代码保护对象Docreatebean (string beanname,rootbeandefinition MBD,@ NullableObject [] args)抛出BeancreationException {//省略大量代码try {//返回方法populateBean()在A完成对属性B的检查和组装后,继续执行this.populate bean (beanname,MBD,instancewrapper)向下;exposedObject = this . initialize bean(bean name,exposed object,mbd);} catch(Throwable var 18){ if(var 18 instance of BeanCreationException & amp;& ampbean name . equals(((BeanCreationException)var 18)。get beanname())){ throw(BeanCreationException)var 18;} throw new BeanCreationException(mbd . getresourcedescription(),beanName,“bean初始化失败”,var 18);} if(earlysingletonexposure){//A被执行到方法getSingleton(),这将从L2缓存中取出A。object earlysingletonreference = this . get singleton(bean name,false);if (earlySingletonReference!= null) {//省略很多代码} }//省略很多代码}继续执行,最终转到addSingleton()方法,将A添加到一级缓存中,将A从二级缓存中删除。 这样,两个循环依赖的bean A和B被放入一级缓存中。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)
【技术支持|常见问题】别告诉我你没看过邰方这两则有思想的创意广告! (2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部