Spring循环依赖问题

Spring循环依赖问题

  • 一、spring循环依赖
  • 二、spring解决循环依赖(三级缓存)

一、spring循环依赖

Spring解决循环依赖是有前置条件的

出现循环依赖的Bean必须要是单例
依赖注入的方式不能全是构造器注入的方式(很多博客上说,只能解决setter方法的循环依赖,这是错误的)

其中第一点应该很好理解,第二点:不能全是构造器注入是什么意思呢?我们还是用代码说话

@Component
public class A {
//	@Autowired
//	private B b;
	public A(B b) {

	}
}


@Component
public class B {

//	@Autowired
//	private A a;

	public B(A a){

	}
}

在上面的例子中,A中注入B的方式是通过构造器,B中注入A的方式也是通过构造器,这个时候循环依赖是无法被解决,如果你的项目中有两个这样相互依赖的Bean,在启动时就会报出以下错误:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'a': Requested bean is currently in creation: Is there an unresolvable circular reference?

为了测试循环依赖的解决情况跟注入方式的关系,我们做如下四种情况的测试

依赖情况 依赖注入方式 循环依赖是否被解决
AB相互依赖(循环依赖) 均采用setter方法注入
AB相互依赖(循环依赖) 均采用构造器注入
AB相互依赖(循环依赖) A中注入B的方式为setter方法,B中注入A的方式为构造器
AB相互依赖(循环依赖) B中注入A的方式为setter方法,A中注入B的方式为构造器

从上面的测试结果我们可以看到,不是只有在setter方法注入的情况下循环依赖才能被解决,即使存在构造器注入的场景下,循环依赖依然被可以被正常处理掉。

二、spring解决循环依赖(三级缓存)

(1)、三级缓存定义

看源码的DefaultSingletonBeanRegistry中有三个 Map 对象

	/** Cache of singleton objects: bean name to bean instance. */
	/** 一级缓存,可以理解为单例池 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

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

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

singletonObjects:存放初始化后的单例对象,也就是完成的 bean 对象
earlySingletonObjects:存放实例化,未完成初始化的单例对象(未完成属性注入的对象),也是用来解决性能问题
singletonFactories:存放 ObjectFactory 对象,存放的是工厂对象,也是用来解决 aop 的问题

(2)、核心方法refresh(刷新)

finishBeanFactoryInitialization方法
重点解析:解决循环依赖。
三级缓存可以解决循环依赖。

  • singletonObjects:一级缓存(单例池:存放经历了完整生命周期的bean对象)

  • earlySingletonObjects:二级缓存(存放早期暴露出来的bean对象,bean生命周期尚未结束)

  • singletonFactories:三级缓存----单例工厂(存放可以生成bean工厂–准备生产)
    3个map+四个方法(解决循环依赖)

  • getSingleton

  • doCreateBean:添加bean

  • populateBean:属性填充

  • addSingleton:将bean设置到一级缓存,且删除二级和三级
    Spring循环依赖问题_第1张图片

你可能感兴趣的:(spring,java,缓存)