Spring三级缓存、循环依赖相关问题

内容来自于 知乎文章

Spring加载bean的流程

  1. 首先根据配置文件或者启动类把左右bean注册成bean定义。bean定义就是用于映射bean和java类的一个标签。
  2. 遍历所有bean定义的beanName,通过调用 **BeanFactory的getBean(beanName)**方法,创建、初始化并返回bean实例。

三级缓存主要关注getBean方法中具体的流程

GetBean()方法的流程

  1. 依次从一级-三级缓存中尝试获取bean。
  2. 对于每一级缓存,如果没有bean:
    2.1先把beanName标记为正在创建
    2.2通过class获取构造方法通过反射创建实例。
    2.3如果beanName状态为正在创建,则把它的工厂对象放入三级缓存。
  3. 初始化实例对象、移除正在创建标记、将实例放入一层缓存、清理二级、三级缓存的内容、返回实例。

三级缓存和代理的关系?

其实,如果要打破循环依赖,直接把实例化的对象放到二级缓存中,发现依赖时直接去二级缓存中取就能解决了,但是为什么要再弄个三级缓存放bean的工厂对象呢?

一级缓存

用了一个ConcurrentHashMap,线程安全的哈希表。
在这里插入图片描述
首先,先确定一级缓存的重要性,所有的能供我们用的bean都在这里,项目运行时,获取bean都是从这里获取的。

二级缓存

在这里插入图片描述

二级缓存叫做 earlySingletonObjects,存放实例化但是没初始化的bean。

三级缓存

在这里插入图片描述
从泛型能看出,三级缓存这个map存的是一个ObjectFactory,它有一个方法叫做 getEarlyBeanReference(),用于生成实例化但没初始化的对象,用于放入二级缓存。
在这里插入图片描述
如果这个bean有初始化的后置逻辑,需要遍历它所有的后置处理processor。通过另一个getEarlyBeanReference方法获取到一个bean,然后返回这个bean。这是在干什么?
我们去看下这个getEarlyBeanReference()的方法:在一个创建代理的类中实现的:
在这里插入图片描述
这里最终返回的是,wrapIfNecessary()的结果,也就是一个代理对象。因此可以得出结论:如果bean有后置逻辑,需要代理时,三计缓存中工厂获取bean的逻辑中,会返回bean的代理对象而不是bean对象。
并且要保证如果其余地方有引用当前bean时,获取的时同一个引用,因此会将这里的bean从工厂中拿出后立刻放入二级缓存。(下次来直接取二级缓存中的,就不会出发工厂的getBean方法了)

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值