何为循环依赖
在创建Bean是 两个或像两个以上的bean 之间相互引用了对方并且形成了依赖闭环。
<bean id="car" class="com.sane.base.factory.Car">
<property name="mobile" ref="mobile"></property>
</bean>
<bean id="mobile" class="com.sane.base.factory.Mobile">
<property name="car" ref="car"></property>
</bean>
出现循环依赖的三种代码场景
- 构造器依赖
- getter/setter 依赖
- 原型方式依赖
Spring 针对三种场景的处理方案
- 构造器依赖时 无法解决循环依赖,只能抛出BeanCurrentlyInCreationException
2.原型依赖时同样抛出BeanCurrentlyInCreationException
3.get/set 方式时可以通过三级缓存解决
关键词:提前暴露,三级缓存
Spring创建Bean时使用到的三级缓存的定义和说明
- singletonObjects:一级缓存,用ConcurrentHashMap<String, Object>存储 <beanName,单例对象实例>这里的bean是已经创建完成的,该bean经历过实例化->属性填充->初始化以及各类的后置处理。因此,一旦需要获取bean时,我们第一时间就会寻找一级缓存
- earlySingletonObjects:二级缓存,该缓存key = beanName, value = bean;这里跟一级缓存的区别在于,该缓存所获取到的bean是提前曝光出来的,是还没创建完成的。也就是说获取到的bean只能确保已经进行了实例化,但是属性填充跟初始化还没有做完(AOP情况后续分析),因此该bean还没创建完成,仅仅能作为指针提前曝光,被其他bean所引用
- singletonFactories:三级缓存,该缓存key = beanName, value = beanFactory;在bean实例化完之后,属性填充以及初始化之前,如果允许提前曝光,spring会将实例化后的bean提前曝光,也就是把该bean转换成beanFactory并加入到三级缓存。在需要引用提前曝光对象时再通过singletonFactory.getObject()获取。