Spring的循环依赖
什么是循环依赖
如果不考虑spring的IOC容器,循环依赖不是一个问题,在java中只需要这么注入
但是Spring的对象并不是new出来的,而是通过一系列Bean的生命周期,就是因为Bean的生命周期才会出现循环依赖的问题
Bean的生命周期
spring,Bean是如何生成的就称为生命周期
1、Spring扫描Class的到BeanDefinition
2、根据BeanDefinition去生成Bean
3、首先根据class推断构造方法
4、根据推断出来的构造方法,反射得到一个对象(暂时称为原始对象)
5、填充原始对象的属性(依赖注入)
6、如果原始对象的某个方法被AOP代理了,那么这个对象就需要用一个代理对象去代理原有对象
7、把最终生成的代理对象放入单例池中(singletonObjects),下次getBean直接从单例池中拿
循环依赖出现问题
解决循环依赖思路解析
上述思路可以解决循环依赖的问题,但是如果A对象需要代理的话,必须使用三级缓存的思路
验证
上述思路,启动Spring的时候会报异常,就是因为放入单例池的对象并不是代理对象的问题
三级缓存
这里为了保证lamdba只能执行一次,在执行完后会将三级缓存删除
函数接口会调用下面的方法,这里会将原有对象再放到一个Map里边
这里注意一个逻辑,earlyProxyReferences这个缓存如果这个原有对象之前有被代理对象的话,这里就会返回原有对象,如果之前没有生成过代理对象就生成代理对象。可以概括为,如果有它循环依赖就返回它自己,没有就生成代理对象返回。不会再一次生成代理
那么生成代理对象是在这里
这里会再次执行getSingleton(Aservice)的方法,因为在构造B的过程中执行了A的lamdba,把A放进了二级缓存,所以这里会从二级缓存拿到对象,放到单例池中。