聊聊spring的三级缓存源码跟踪

一.下面三个缓存容器

缓存逻辑:实例化A之后,并且将beanFactory放到三级缓存中,然后执行populateBean属性注入

1.如果其他Bean没有引用这个A,那么就不会从三级缓存获取BeanFactory,和调用BeanFactory的getObject方法了,二级缓存此时就不会用到。populateBean执行完成之后就直接bean放到一级缓存中,清除其他两个缓存

2.如果有循环依赖,populateBean执行的时候就会,去三级缓存获取BeanFactory,然后调用beanFactory的 getObject方法生成代理对象,并加入到二级缓存中,属性注入完成,从二级缓存获取bean,然后加入到一级缓存并清空其他两个缓存

注意:没有存在循环依赖的话,代理对象是在初始化完成后进行的,如果有循环依赖,那么代理对象在属性注入阶段就被创建了,这样才能将代理对象注入到其他对象中。

/** Cache of singleton objects: bean name to bean instance. 一级缓存 */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of early singleton objects: bean name to bean instance. 二级缓存 */ private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** Cache of singleton factories: bean name to ObjectFactory. 三级缓存 */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 复制代码

二.创建bean主要的方法是在AbstractBeanFactory.doGetBean方法关键的方法就是getSingleton这两个重载的方

1.1 从三个缓存中获取bean

@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // Quick check for existing instance without full singleton lock 
//从一级缓存中获取 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 
//从二级缓存中获取 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //没有获取到,加锁再重新获取 synchronized (this.singletonObjects) { // Consistent creation of early reference within full singleton lock 
//一级缓存获取 singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //二级缓存获取 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { 
//三级缓存获取,存的是ObjectFactory ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } } } return singletonObject; } 复制代码

1.2 没有缓存中获取到bean的话,接下就会调用另一个重载的getSingleton方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) 
{ Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { 
//实例化前的校验,是否正在创建,正在创建的话会抛出异常 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { //创建bean的关键入口,里面的主要的逻辑代码在AbstractAutowireCapableBeanFactory.doCreateBean方法中 //创建好bean实例之后,会接着放到三级缓存中 //addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //add方法主要逻辑将1.ObjectFactory放到三级缓存 2.移除二级缓存 //getEarlyBeanRefrence主要就是调用SmartInstantiationAwareBeanPostProcessor接口实现, //代理类就是在这一步去处理的(这个地方不会执行这个逻辑,在获取三级缓存的时候, //得到ObjectFactory对象调用getObject方法才会执行(singletonObject = singletonFactory.getObject();) 
//情况1.如果它的属性对象也引用了它,就出现了循环依赖。比如A、B互相依赖,当前是A,A实例化 //了,执行populateBean属性注入,执行B的实例化过程,B实例化然后执行populateBean,去获取A,从1.1的代码, //走到三级缓存,从三级缓存中获取ObjectFactory,然后getObject执行一些列代理接口,得到最终的bean,并把bean放到二级缓存 
//情况2.如果对象没有循环依赖,这个在下面这个方法执行完成后还是在三级缓存中 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { //异常捕捉代码省略 .......... } if (newSingleton) { //下面四行注释是addSingleton方法copy出来的,将bean放到一级缓存中,移除三级缓存和二级缓存中的数据。上面说了两种情况,有循环依赖的话此时bean在二级缓存,没有循环依赖的话在三级缓存,这个地方没有从三级缓存拿的话,岂不是代理逻辑就没了 
//this.singletonObjects.put(beanName, singletonObject); //this.singletonFactories.remove(beanName); //this.earlySingletonObjects.remove(beanName); //this.registeredSingletons.add(beanName); addSingleton(beanName, singletonObject); } } return singletonObject; } } 复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值