Spring三级缓存核心思想

spring在启动时候,会创建bean,并给bean填充属性,这事会使用到三级缓存

	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存

我们在理解三级缓存前,先明白什么是实例化,什么叫初始化
实例化就是,创建了对象,不为null了
初始化是,不仅实例化了,属性也得到填充

一、第一级缓存特别简单,保存所有已经实例化并且初始化好的bean;
如果不存在循环依赖,那只需要一级缓存就可以了,可是循环依赖的存在,导致一级缓存不够,举个例子解释下循环依赖,A类有B属性,B类有A属性,在A类初始化过程中发现需要B,就先进行B类的初始化,这时又需要A,那就会进入死循环,不仅仅是A->B->A这种,A->B->C->A也是叫循环依赖,一级缓存是无法解决循环依赖的
二、这时候,我们就需要借用一个集合,存储已经实例化,但是没有初始化的对象,那就是第二级缓存;,我们在实例化A后,将A存放进二级缓存中,再去初始化B,需要使用A填充B属性时,从二级缓存中取,完美解决循环依赖问题
既然循环依赖已经解决,为什么还要有第三级缓存?那又要明白一个新的概念,代理对象,当我们使用AOP时,我们使用的对象,已经不是原生对象,而是代理对象。正常的创建代理对象流程如下:初始化普通对象,创建代理对象,普通对象作为代理对象的属性,当其他对象需要引用该对象时,使用其代理对象。以上环节如果出现循环依赖,怎么做?其实不用三级缓存,也能实现,比如:A为需要使用代理对象,实例化A之后,立即实例化A的代理对象,将A的代理对象放到二级缓存,需要引用A的时候,可以在二级缓存内查询。但是,创建A代理对象的时候,要尽量先初始化A的普通对象(此为规范),所以在实例化A对象后,不创建A代理对象,而是先将A存到三级缓存,初始化A时,如果A使用到B,B需要引用A时,在三级缓存内查询到,此时再创建A的代理对象,因为此时A还没有初始化完成,所以还是先保存至二级缓存,这就是三级缓存的作用。三、三级缓存的作用是,在尽量先初始化对象后再创建代理对象的前提下,将对象先保存至三级缓存,能够解决循环依赖(三级缓存在循环依赖中后续会进二级缓存,没有循环依赖,会进一级缓存)

那为什么会有spring解决不了的循环依赖呢?
1、使用@Scope(“prototype”)[作用是创建新对象,不从缓存中取]的类,A、B循环依赖,且都有该注解;很容易理解,不从缓存中取,那就进入死循环了
2、属性加在构造器里的;此时不是初始化对象用到其他对象,是在实例化时候就需要了,那就没办法了
3、@Async 增强的 Bean 的循环依赖;@Async标记后生成代理对象,和AOP的代理对象不同,所以不会进三级缓存。普通的 AOP 代理都是通过 AbstractAutoProxyCreator 来生成代理类的,AbstractAutoProxyCreator 实现了 SmartInstantiationAwareBeanPostProcessor。而 @Async 标记的类是通过 AbstractAdvisingBeanPostProcessor 来生成代理的,AbstractAdvisingBeanPostProcessor 没有实现 SmartInstantiationAwareBeanPostProcessor。
怎解决上面的问题
@Lazy

三级缓存最好的体现

	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;
	}

三级缓存外,还有一个缓存
使用FactoryBean的名字,实际是具体的bean

private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值