Spring 解决循环依赖

Posted lisin-lee-cooper

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 解决循环依赖相关的知识,希望对你有一定的参考价值。

一. Bean的生命周期

二. 什么是什么是三级缓存

	/** 1级缓存 Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 2级缓存 Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** 3级缓存 Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

获取单例bean时

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;
	

第一步:第一层缓存singletonObjects 中,获取单例bean,拿到了直接使用,没有拿到则拿二级缓存;
第二步:在二级缓存earlySingletonObjects中,提前暴露的Bean;
第三步:在三级缓存中查找对应的工厂对象,利用拿到的工厂对象去获取包装后的bean。

如果不使用三级缓存singletonFactories,无法解决AOP后置增强问题,
多一级缓存意义就是在bean循环引用过程中,发生了AOP增强时,避免返回真实对象而非代理对象Proxy。

三. 为什么用三级缓存不用两级缓存

初始spring是没有解决循环引用问题的,设计原则是 bean 实例化、属性设置、初始化之后 再 生成aop对象,但是为了解决循环依赖但又尽量不打破这个设计原则的情况下,使用了存储了函数式接口的第三级缓存;
如果使用二级缓存的话,可以将aop的代理工作提前到 提前暴露实例的阶段执行; 也就是说所有的bean在创建过程中就先生成代理对象再初始化和其他工作; 但是这样的话,就和spring的aop的设计原则相驳,aop的实现需要与bean的正常生命周期的创建分离; 这样只有使用第三级缓存封装一个函数式接口对象到缓存中, 发生循环依赖时,触发代理类的生成。

以上是关于Spring 解决循环依赖的主要内容,如果未能解决你的问题,请参考以下文章

Java面试小短文Spring 如何解决循环依赖?

Java面试小短文Spring 如何解决循环依赖?

图解 Spring 解决循环依赖,学不会接着砍!

spring的循环依赖是什么,设计的时候怎么避免,而spring又是怎么解决的?

spring的循环依赖是什么,设计的时候怎么避免,而spring又是怎么解决的?

spring-循环依赖