电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

spring解決循環依賴

瀏覽:25日期:2023-08-11 11:21:51

概述

循環依賴就是依賴關系形成環,比如最簡單的循環依賴:A對象依賴B,B對象依賴A

屬性注入與循環依賴

如果是構造器注入,如果循環依賴對象沒法構建,因為還未實例化 如果是屬性注入但是作用域是prototype,spring不會緩存其對象實例,也不能處理循環依賴的情況 如果是屬性注入singleton的,其bean的實例化過程與屬性注入過程是分開的,并且spring提供了三個map(就是大家說三級緩存)來實現。

spring屬性注入處理循環依賴的方式

通過以下xml方式配置一個循環依賴的示例:

<bean class='com.example.leetcode.spring.bean.Person'> <property name='parent' ref='person2'></property> <property name='name' value='tom'></property></bean><bean class='com.example.leetcode.spring.bean.Person'> <property name='parent' ref='person1'></property> <property name='name' value='jack'></property></bean>

spring循環依賴處理幾個關鍵位置:

獲取bean對象

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 這里會檢查單例bean是否已經在注冊表,并返回。 // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) {logger.trace('Returning eagerly cached instance of singleton bean ’' + beanName + '’ that is not fully initialized yet - a consequence of a circular reference'); } else {logger.trace('Returning cached instance of singleton bean ’' + beanName + '’'); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } ...}

DefaultSingletonBeanRegistry(單例對象注冊表)的幾個關鍵屬性。

// 用來存儲已經創建好的單例對象 /** Cache of singleton objects: bean name to bean instance. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 用來存儲單例beanname到ObjectFactory的映射 /** Cache of singleton factories: bean name to ObjectFactory. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 用來提前存儲還未初始化好的單例對象 /** Cache of early singleton objects: bean name to bean instance. */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

DefaultSingletonBeanRegistry.getSingleton()的實現.

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 { ... instanceWrapper = createBeanInstance(beanName, mbd, args); ... // 檢查是否提前將單例bean存入緩存 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace('Eagerly caching bean ’' + beanName + '’ to allow for resolving potential circular references'); } // 這里將beanname與工廠映射放入緩存注冊表中(也就是上面的singletonFactories) addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } ... // 注入依賴屬性 populateBean(beanName, mbd, instanceWrapper); ...}

假設我們從beanfactory獲取person1對象, 循環依賴處理流程如下:

1.通過AbstractBeanFactory.doGetBean('persion1')獲取對象

2.因為一開始通過DefaultSingletonBeanRegistry.getSingleton()什么都沒有,進入AbstractAutowireCapableBeanFactory.doCreateBean()進行創建

3.AutowireCapableBeanFactory.doCreateBean()里面執行完創建邏輯,因為是singleton將beanname與工廠的映射加入到addSingletonFactory()到緩存

4.開始處理person1對象的屬性依賴populateBean()

5.當發現person1的parent屬性是一個引用時,通過beanfactory.getBean('person2')獲取依賴對象(org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference)

6.此時進入person2的創建流程, person2也沒有緩存,開始實例化并加入到addSingletonFactory()到緩存

7.person2在通過populateBean()注入屬性依賴發現依賴person1, 此時通過beanfactory.getBean('person1')獲取依賴對象

8.此時AbstractBeanFactory.doGetBean('persion1')獲取對象執行到getSingleton('person1')進行以下判斷:

從singletonObjects.get(beanName)獲取到null 進入if條件,對singletonObjects同步 從earlySingletonObjects.get(beanName);獲取也為null 進入內層if,通過singletonFactories.get(beanName);獲取到最開始bean實例化之后的beanname與工廠緩存信息 獲取到僅實例化完成的bean,并earlySingletonObjects.put(beanName, singletonObject); 然后刪除singletonFactories.remove(beanName);

9.此時從getSingleton('person1')返回了一個僅實例化尚未注入的bean引用

10.person2在第7步獲取到person1僅實例化未注入的對象引用。

11.person2完成屬性注入并返回。

12.person2被addSingleton(beanName, singletonObject);中singletonObjects.put(beanName, singletonObject)緩存,并刪除singletonFactories.remove(beanName);earlySingletonObjects.remove(beanName);

13.person1在5步獲取到person2的對象并完成屬性注入

14.person1對象返回(因為一開始person2獲取的是person1的引用,此時person1完成注入是能看到注入后的對象)

15.person1被addSingleton(beanName, singletonObject);中singletonObjects.put(beanName, singletonObject)緩存,并刪除singletonFactories.remove(beanName);earlySingletonObjects.remove(beanName);

16.返回最終的person1對象

關于三個map(三級緩存)

在出現循環依賴時,三個map之間的流程如下:

先從singletonFactories獲取工廠,并通過getObject獲取對象并移除緩存,將對象緩存到earlySingletonObjects通過earlySingletonObjects獲取提前曝光的對象對象創建并初始化完成之后,對象信息保留在singletonObjects并移除過earlySingletonObjects中的緩存

earlySingletonObjects二級緩存是雞肋嗎?

earlySingletonObjects緩存的目的是,通過三級緩存在獲取對象會執行一些列的后置處理器,通過earlySingletonObjects來緩存提升性能。

以上就是spring解決循環依賴的詳細內容,更多關于sping 循環依賴的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
主站蜘蛛池模板: 北京租车公司_汽车/客车/班车/大巴车租赁_商务会议/展会用车/旅游大巴出租_北京桐顺创业租车公司 | 木材烘干机,木炭烘干机,纸管/佛香烘干设备-河南蓝天机械制造有限公司 | 生产自动包装秤_颗粒包装秤_肥料包装秤等包装机械-郑州鑫晟重工科技有限公司 | 膜片万向弹性联轴器-冲压铸造模具「沧州昌运模具」 | 网站建设,北京网站建设,北京网站建设公司,网站系统开发,北京网站制作公司,响应式网站,做网站公司,海淀做网站,朝阳做网站,昌平做网站,建站公司 | 智慧食堂_食堂管理系统_食堂订餐_食堂消费系统—客易捷 | 镀锌方管,无缝方管,伸缩套管,方矩管_山东重鑫致胜金属制品有限公司 | 镀锌钢格栅_热镀锌格栅板_钢格栅板_热镀锌钢格板-安平县昊泽丝网制品有限公司 | 微波消解仪器_智能微波消解仪报价_高压微波消解仪厂家_那艾 | 紧急泄压人孔_防爆阻火器_阻火呼吸阀[河北宏泽石化] | 一航网络-软件测评官网 | 恒温恒湿试验箱_高低温试验箱_恒温恒湿箱-东莞市高天试验设备有限公司 | 杭州中央空调维修_冷却塔/新风机柜/热水器/锅炉除垢清洗_除垢剂_风机盘管_冷凝器清洗-杭州亿诺能源有限公司 | 智慧食堂_食堂管理系统_食堂订餐_食堂消费系统—客易捷 | 金属管浮子流量计_金属转子流量计厂家-淮安润中仪表科技有限公司 | TYPE-C厂家|TYPE-C接口|TYPE-C防水母座|TYPE-C贴片-深圳步步精 | 盘煤仪,盘料仪,盘点仪,堆料测量仪,便携式激光盘煤仪-中科航宇(北京)自动化工程技术有限公司 | 紧急切断阀_气动切断阀_不锈钢阀门_截止阀_球阀_蝶阀_闸阀-上海上兆阀门制造有限公司 | 跨境物流_美国卡派_中大件运输_尾程派送_海外仓一件代发 - 广州环至美供应链平台 | 工程管道/塑料管材/pvc排水管/ppr给水管/pe双壁波纹管等品牌管材批发厂家-河南洁尔康建材 | 钢结构-钢结构厂房-钢结构工程[江苏海逵钢构厂] | 识禅_对禅的了解,从这里开始 | 绿叶|绿叶投资|健康产业_绿叶投资集团有限公司 | 英思科GTD-3000EX(美国英思科气体检测仪MX4MX6)百科-北京嘉华众信科技有限公司 | 成都竞价托管_抖音代运营_网站建设_成都SEM外包-成都智网创联网络科技有限公司 | 不锈钢法兰-碳钢法兰-法兰盘生产加工厂家-[鼎捷峰]-不锈钢法兰-碳钢法兰-法兰盘生产加工厂家-[鼎捷峰] | 快速门厂家批发_PVC快速卷帘门_高速门_高速卷帘门-广州万盛门业 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 | 深圳法律咨询【24小时在线】深圳律师咨询免费| 3d可视化建模_三维展示_产品3d互动数字营销_三维动画制作_3D虚拟商城 【商迪3D】三维展示服务商 广东健伦体育发展有限公司-体育工程配套及销售运动器材的体育用品服务商 | 【北京写字楼出租_写字楼租赁_办公室出租网/出售】-远行地产官网 | WF2户外三防照明配电箱-BXD8050防爆防腐配电箱-浙江沃川防爆电气有限公司 | 深圳货架厂_仓库货架公司_重型仓储货架_线棒货架批发-深圳市诺普泰仓储设备有限公司 | 伟秀电气有限公司-10kv高低压开关柜-高低压配电柜-中置柜-充气柜-欧式箱变-高压真空断路器厂家 | 西安展台设计搭建_西安活动策划公司_西安会议会场布置_西安展厅设计西安旭阳展览展示 | 食品级焦亚硫酸钠_工业级焦亚硫酸钠_焦亚硫酸钠-潍坊邦华化工有限公司 | 粉末冶金-粉末冶金齿轮-粉末冶金零件厂家-东莞市正朗精密金属零件有限公司 | 深圳活动策划公司|庆典策划|专业公关活动策划|深圳艺典文化传媒 重庆中专|职高|技校招生-重庆中专招生网 | 分轨 | 上传文件,即刻分离人声和伴奏| 宁夏活性炭_防护活性炭_催化剂载体炭-宁夏恒辉活性炭有限公司 | 衬塑设备,衬四氟设备,衬氟设备-淄博鲲鹏防腐设备有限公司 | 全自动固相萃取仪_高通量真空平行浓缩仪-勤业永为 |