介绍
ABean创建-->依赖了B属性-->触发BBean创建--->B依赖了A属性--->需要ABean(但ABean还在 创建过程中)
@Service
public class A{
@Autowire
B b;
}
@Service
public class B{
@Autowire
A a;
}
解决方法
-
@Lazy注解:
-
当发生循环依赖时,如果依赖注入需要一个Bean,并且这个Bean加了
@Lazy
注解,Spring容器会生成一个代理对象(Proxy)来模拟这个Bean的引用。这个代理对象并不是真正的Bean实例,而是一个占位符,它会在第一次被使用时,触发所代理的Bean的初始化。 -
注意:@Lazy注解只能解决单例Bean之间的循环依赖问题,因为单例Bean在容器启动时就会被创建。对于原型(prototype)作用域的Bean,@Lazy注解不起作用,因为原型Bean每次获取时都会创建一个新的实例。
-
-
三级缓存:
-
详细分析:
-
一级缓存:
-
就是singletonObjects,是CourrentHashMap。
-
缓存 经过完整生命周期 的bean。
-
-
二级缓存:
-
就是earlysingletonObject,是HashMap。
-
缓存 未经完整生命周期 的bean。如果哪个bean出现了循环依赖,就会在推断构造方法后生成bean普通对象提前暴露存放到earlysingletonObjects,如果要进行AOP,就把代理对象存储到earlysingletonObjects,否则将原始对象存储到earlysingletonObjects,但不管怎么样,就算是代理对象,也是未经完整生命周期的代理对象,所以放入earlysingletonObjects我们会统称为 未经完全生命周期 的bean.
-
-
三级缓存:
-
就是singletonFactories,也是HashMap。
-
缓存的是一个ObjectFactory,也就是一个Lambda表达式,在每个bean实例化之后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式 可能用到,也可能用不到。没有出现循环依赖就用不到,就会按照正常的生命周期执行完,将对象存入到singletonObjects,如果出现了循环依赖,就会在依赖注入时到三级缓存中拿Lambda表达式,并执行Lambda表达式生成一个对象放到二级缓存中((如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象))。
-
-
其实还要一个缓存,就是earlyProxyReferences,它用来记录某个原始对象是否进行过AOP。
-
-
简单分析:
-
singletonObjects中缓存的是已经经历了完整生命周期的bean对象。
-
earlySingletonObjects比singletonObjects多了一个early,表示缓存的是早期的bean对象。早期是什么意思?表示Bean的生命周期还没走完就把这个Bean放入了earlySingletonObjects。
-
singletonFactories中缓存的是ObjectFactory,表示对象工厂,表示用来创建早期bean对象的工厂。
-
-
-