以下讲的循环依赖时基于单例模式下的@Autowired或者set方法的spring的循环依赖
spring循环依赖 搞懂之前需要了解bean的创建过程
大概步骤如下:
1、org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String, Class<T>, Object[], boolean) 创建bean的方法
2、org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String)
单例池中获取bean对象,第一次创建bean的时候肯定返回空
循环依赖发生时 进入该方法时候会从三级缓存singletonFactories中执行lambda表达式 生成代理对象,并且放置到二级缓存中
该方法里面个set集合 singletonsCurrentlyInCreation注意下面会设置值
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);//从一级缓存中获取if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//isSingletonCurrentlyInCreation 是从一个set中获取 意思是正在创建的对象 当你bean开始创建的时候就会设置进入这个setsynchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();//执行lambda表达式 提前aopthis.earlySingletonObjects.put(beanName, singletonObject);//放入二级缓存this.singletonFactories.remove(beanName);//从三级缓存中移除}}}}return singletonObject;}
3、org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>) 这个方法第二个参数是个lambda表达式 只有真正调用getObject时候才会执行
注意此getSingleton 并非步骤2中的getSingleton 参数不一样
这个方法里面会做如下几件事情:
3.1.、beforeSingletonCreation 也就是会往singletonsCurrentlyInCreation这个set中放入该bean,代表bean正在创建中
3.2、singletonFactory.getObject 真正执行lambda表达式 也就是执行下面这个方法 org.springframework.beans.factory.support.AbstractBeanFactory.createBean(String, RootBeanDefinition, Object[])
实现类在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
真正实现bean的生命周期的方法是
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])
3.2.1 、createBeanInstance 推断构造方法 实例化
3.2.2、addSingletonFactory 将该bean设置到三级缓存singletonFactories中去
3.2.3、populateBean 属性填充 当通过@Autowired或者set方法注入的时候 会在这个步骤里面填充属性 并且发现循环引用 重新调用步骤2
3.2.4、initializeBean 初始化bean
举例说明 如下代码块 A→B B→A 发生了循环引用
@Componentpublic class A {@AutowiredB b;}@Componentpublic class B {@AutowiredA a;}