BeanCurrentlyInCreationException简单剖析
Spring为解决循环依赖问题,会创建 early bean(如果是单例,且当前处于正在创建状态,则符合创建early bean的条件)。
如 A -> B, B->A
如果假设当前正在创建bean A,A是单例,则此时会创建一个 early bean = new A();
然后继续创建 bean A,此时需要进行属性绑定,则此时会创建 bean B,创建B时发现B同时也需要绑定属性 A,这时便出现了循环依赖。
此时由于A尚未创建完成,所以会从early bean Map中查找A进行属性绑定。注意此时绑定的 early bean A并非最终的 real bean(如果A中包含事务或进行了AOP处理,那么最终生成的 real bean A将会是一个代理类)。
待real bean A创建完成后,判定early bean A 是否与 real bean A是同一个对象,如果是,万事大吉;如果不是,则继续判定;
查找依赖A的bean列表,查看列表中是否存在已经创建完成的bean,如果bean均为创建完成,那么也万事大吉;
如果存在创建完的bean,意味着这些bean引用了错误的 bean A,这时候Spring会抛出异常BeanCurrentlyInCreationException。
解决该问题的关键是尽量减少循环依赖,如果实在需要循环依赖,可以将某一方(通常是引用了错误bean的这一方)的属性绑定设置为 @Lazy便可以解决该问题。
参考
spring version: 5.2.10.RELEASE
1. 创建bean源码
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
2. 获取单例bean源码
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)