spring三级缓存

目录

文章目录

前言

一、spring三级缓存是什么?

二、分析步骤

总结


前言

spring三级缓存用来解决spring的循环依赖问题

目前循环依赖只在属性set注入且单例的情况下才能解决

构造器注入和多例的循环依赖情况下是无法解决的


提示:以下是本篇文章正文内容,下面案例可供参考

一、spring三级缓存是什么?

singletonObjects   <ConCurrentHashMap<>>  一级缓存
singletonFactories  <HashMap<>>  三级缓存
earlySingletonObjects  <HashMap<>> 二级缓存

二、分析步骤

1.循环依赖示例:

@Service
public class AService {

    private BService bService;

    public AService() {

        System.out.println("Aservice 构造方法执行---------");
    }

    public BService getbService() {
        return bService;
    }

    public void setbService(BService bService) {
        this.bService = bService;
    }
}




@Service
public class BService {

    private AService aService;


    public BService() {
        System.out.println("bService 构造方法--------");
    }

    public AService getaService() {
        return aService;
    }

    public void setaService(AService aService) {
        this.aService = aService;
    }
}

当容器初始化加载两个bean时,会造成A,B相互依赖,查看bean生命周期,可以追踪循环依赖的解决方式

首先容器会通过doGetBean()获取AService,

/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	@Nullable
	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;
	}
// 如果获取不到,则创建 
if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            //创建
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {

							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}				

通过doCreateBean()方法创建Aservice

// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		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");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}




//放入三级缓存后,准备初始化bean实例,接着填充属性操作
// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

会先把AService放入三级缓存,

key: beanName     value值 : () -> getEarlyBeanReference(beanName, mbd, bean)

具体的addSingletonFactory() 方法

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

AService填充属性,需要注入BService

解析依赖方法:

private Object resolveReference(Object argName, RuntimeBeanReference ref) {
		try {
			Object bean;
			String refName = ref.getBeanName();
			refName = String.valueOf(doEvaluate(refName));
			if (ref.isToParent()) {
				if (this.beanFactory.getParentBeanFactory() == null) {
					throw new BeanCreationException(
							this.beanDefinition.getResourceDescription(), this.beanName,
							"Can't resolve reference to bean '" + refName +
							"' in parent factory: no parent factory available");
				}
				bean = this.beanFactory.getParentBeanFactory().getBean(refName);
			}
			else {
                //此处会去获取BService bean实例
				bean = this.beanFactory.getBean(refName);
				this.beanFactory.registerDependentBean(refName, this.beanName);
			}
			if (bean instanceof NullBean) {
				bean = null;
			}
			return bean;
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					this.beanDefinition.getResourceDescription(), this.beanName,
					"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
		}
	}

而容器中还没有Bservice的Bean,及需要先创建BService的bean

BService的创建也是先经过上述步骤

先把BService的未成品的bean放入三级缓存

然后BService的bean 填充属性 AService

这时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);
					//从一级缓存未找到AService的Bean且allowEarlyReference为true,
                    //则把AService的Bean放到二级缓存中
                    if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

之后BService的Bean属性填充完毕,创建实例Bean完成,让后将Bean放入的一级缓存

/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * <p>To be called for eager registration of singletons.
	 * @param beanName the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

接下来回到Aservice的Bean的 填充属性方法

获取到Bservice的Bean实例,

属性填充完毕

再把AService的Bean实例放到一级缓存中,

至此实例化ABService完成


总结

循环依赖似乎只要二级缓存就能解决,为何还要三级缓存,

个人理解:其实在最开始放入三级缓存的value,lambda表达式,即用来解决AOP代理的bean相互依赖的的问题,如果需要代理,则提前暴露代理对象放入的其他缓存,否则提前生成普通代理对象实例放入其他缓存即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值