Spring如何处理循环引用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring如何处理循环引用相关的知识,希望对你有一定的参考价值。
参考技术A 以上就是典型的循环引用场景。熟悉Spring的人都知道Spring是通过三级缓存来处理循环依赖:
下面是本次跟踪的大概流程,主要是关注了三级缓存的变化情况
用大白话来描述一下流程(假定beanA先创建):
Code1:
从Spring真正开始创建对象的 doGetBean 方法开始
Code2:
此时,由于beanA第一次被创建,因此 一级缓存 获取不到对象,返回NULL,再次返回Code1创建beanA
Code3:(注意这里重载了Code2的方法)
首先从一级缓存中尝试获取beanA,如果获取不到则标记当前beanA处于创建状态,通过 ObjectFactory 开始创建beanA
Code4:
首先通过推断出来的构造器创建beanA,接着将beanA放入三级缓存,开始为beanA填充属性,此时会发现beanB尚未创建,进入beanB的创建流程
beanA填充beanB属性完毕,从一、二级缓存中尝试获取缓存中的beanA
Code5:
创建beanB的流程其实类似上面创建beanA的流程,首先在一、二、三级缓存中没有找到beanB,则开始创建beanB
Code6:
这个其实就上面创建beanA的时候执行过得Code2,先从一级缓存获取beanB,没有获取到则标记beanB正在创建,进入创建beanB的流程
beanB经历 实例化、属性填充、初始化 操作之后,清除beanB正在创建标记,并将beanB从 三级缓存 挪到 一级缓存
Code7:
这里与创建beanA过程的Code4一样,创建beanB完毕之后,开始为beanB填充属性beanA
为beanB填充完毕beanA,beanB的创建过程主要步骤( 实例化、属性填充、初始化 )结束
Code8:
为beanB填充属性beanA的时候,Spring再次尝试创建beanA,此时会走到Code1的流程,但是此时Spring已经可以从三级缓存中获取到beanA,因此不会再往下执行beanA的创建,同时会将beanA从 三级缓存 移动到 二级缓存
PS.
经过beanA和beanB的创建,我们发现Spring每次创建一个bean都会尝试先去 一、二、三级缓存 获取,这里其实就是Code2中 getSingleton ,如果一级缓存没有获取到,但是bean正在被创建则尝试去二级缓存获取,二级缓存没有获取到,但是bean允许提前引用则再次尝试从三级缓存获取
Code9:
beanA经历 创建、属性填充、初始化 完毕,重新尝试从缓存中获取
从上面解决循环引用的问题,我们可以总结出,Spring创建对象、装配属性的时候都尝试先从一、二、三级缓存加载创建好的对象,在装配属性的时候如果从三级缓存获取到对象,会移动到二级缓存,此后获取这个对象就会先从二级缓存中获取。
如果采用二级缓存,单纯从解决循环引用的角度来说确实可以实现,就以上面的beanA来说,假设beanB通过二级缓存装配了beanA属性,后续beanA被某些操作重新包装了一次再次放入二级缓存,就会导致同一个beanA属性,在不同的bean中引用了不同的对象。
如何处理 Django 模型中的循环关系?
【中文标题】如何处理 Django 模型中的循环关系?【英文标题】:How to deal with circular relationship in Django models? 【发布时间】:2022-01-18 02:38:30 【问题描述】:我正在尝试编写一个基本数据库来提供我的照片。这看起来很简单,但我就是想不通,尽管思考了几个星期。我正在尝试组合多个相互链接的模型。
照片:包含一些存储数据的文件人物:照片中出现的有关某人的数据/已引起了引用 引言:某人说过的话需要附在照片上(引言不属于那个人的所有照片,而是属于特定的一组照片) 优惠:包含所有报价的概览,其中一张照片作为缩略图和所有照片(有些照片可能有相同的报价,但应该只出现一次)
作为一个模型,因为这里的人们真的很喜欢先看一些代码,所以我做了这个:
class Quote:
person = models.ForeignKey("Person")
photos = models.ManyToManyField("Photo")
class Person:
photo = models.ForeignKey("Photo")
class Photo:
pass
class Offer:
quotes = models.ManyToManyField("Quote")
photos = models.ManyToManyField("Photo")
请以上面的代码为例,因为我已经不知道如何解决这个问题。我尝试了多个不同的版本,但总有一些情况没有被涵盖。在上面的示例中,问题是:Person 和 Quote 独立地附加到 Photos。但是如果没有那个人在那里,就不可能有报价。所以有些信息是加倍的,可能会不同意。我也尝试使用“through=”将 People 和 Quotes 放在一起,但后来遇到了其他问题。
你能推荐任何好的教程或给我一个提示如何处理这些“混乱”的关系吗?
谢谢你, 迈克尔
【问题讨论】:
【参考方案1】:希望我做对了。下图显示了我将如何设置此类结构。
人物:每个人都有多个引号,并且是多张照片的一部分 照片:每张照片都是多个照片集的一部分 引用:每条引用引用一张照片集 Photoset_Photos: 多对多结构将多个照片集与多张照片连接起来 照片集:每个照片集确实包含多张照片,并且可以用多个引号引用 报价:一个报价引用多个照片集,通过此参考,您可以获得他们的照片集和所有照片的所有报价【讨论】:
以上是关于Spring如何处理循环引用的主要内容,如果未能解决你的问题,请参考以下文章