简介
定制化开发什么是循环依赖:定制化开发就是循环引用,俗称“套娃”,比如beanA需要引用BeanB,BeanB需要引用BeanA,定制化开发形成循环关系;
spring bean定制化开发发生循环依赖有三种形式:
1、互相依赖:
eg:a和b定制化开发相互依赖形成循环依赖。如下图:
2、三者之间及其以上的依赖:
eg:多个bean之间形成循环依赖。如下图:
3、自我依赖
eg:a依赖a形成循环依赖。 如下图
spring解决循环依赖的方式
利用缓存机制解决循环依赖问题,spring设计了三级缓存解决循环依赖的问题,分别是一级缓存:singletonObjects;二级缓存:earlySingletonObjects;三级缓存:singletonFactories;
一级缓存:singletonObjects,存放初始化后的单例对象;
二级缓存:earlySingletonObjects,存放实例化,未完成初始化的单例对象(未完成属性注入的对象);
三级缓存:singletonFactories,存放ObjectFactory对象;
三级缓存之间逐级取,流程如下:
1、getBean()获取实例,Spring首先从一级缓存singletonObjects中获取;
2、如果获取不到,就从二级缓存earlySingletonObjects中获取,如果还是获取不到意味着bean没有实例化;
3、这时singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取;(代理也是从三级缓存生产的)
4、如果从三级缓存中获取到就从singletonFactories中移除,并放入earlySingletonObjects中。其实也就是从三级缓存移动到了二级缓存;
5、这个bean存在会等待下一次轮寻的时候去赋值(解析@Autowared,@Resource)注解等,属性赋值完成后,将bean存入一级缓存;
解决循环依赖简单的流程图
对应方法级的具体流程图可以参考,该作者写的十分详细
spring无法解决循环依赖的情况
1、多实例bean通过setter注入的时候
2、构造器注入bean的情况下
3、单例的代理bean通过setter注入
4、设置@DependsOn注解的bean