以以下几个类为实例做原理分析:
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
从spring获取A的实例对象时:
A实例化核心过程:
1、先从单例池中获取实例A,单例池中不存在。
2、标记A为正在创建的实例。
3、执行getSingleton方法获取实例A,第二个参数为一个创建A实例的函数式表达式。
4、再次从单例池中获取实例A,获取不到会执行第二个参数的函数式表达式的方法中的doCreateBean方法,创建未初始化的实例A,再以key、value的形式放进三级缓存singletonFactories,实例A以参数的形式传到lambd表达式中。
5、进行对实例A的populate操作,即属性赋值操作。发现A的属性B需要赋值操作,所以会获取B实例。
6、获取B的实例步骤会重复以上1-5步骤的操作。
7、实例B进行populate操作,发现属性A之后,会在流程中去三个缓存中获取实例A,最终会在第三级缓存中获取到关于A实例的lambd表达式,然后执行lambd表达式,获取到实例A,再放到二级缓存中,删除三级缓存中对应的表达式。
8、通过field.set(bean, value),把A实例赋值给B的属性A,并且最终把初始化完成的实例B放入到一级缓存,并且删除二级缓存、三级缓存中的实例B。实例B初始化流程完成后,接着返回实例B到之前A的执行popupate方法中即步骤5中接着执行。当A的主流程从getSingleton(String beanName, ObjectFactory<?> singletonFactory)执行完之后,已经获取到实例B,并且实例B已经存放到一级缓存中。这个时候A的B属性还没有初始化完。
9、A的主流成会接着往下执行,最终会执行到
inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)
方法中的field.set(bean, value),value为B实例,把B赋值给A的属性B,完成实例A、B循环依赖的赋值。最后A也存放到单例池。
以下为循环依赖流程图