spring源码怎么解决循环依赖?

spring源码怎么解决循环依赖?

1.数据准备

这里先创建2个bean,互相注入,看看spring是怎么解决这个问题的

@Repository
public class BoyFriend {
   @Autowired
   private GirlFriend girlFriend;
}
@Repository
public class GirlFriend {
   @Autowired
   private BoyFriend boyFriend;
}

2.debug分析逻辑

在populateBean打上断点,可以发现调用栈

spring源码怎么解决循环依赖?

一步步分析:

1.AnnotationConfigApplicationContext方法的refresh()方法 因为这里使用的是注解方式配置的容器

2.refresh()的finishBeanFactoryInitialization(beanFactory); 实例化所有的类(懒加载的类除外)

3.finishBeanFactoryInitialization()的beanFactory.preInstantiateSingletons();方法 实例化所有剩余的(non-lazy-init非延时加载的)单例

4.preInstantiateSingletons()的getBean(boyFriend);方法

5.getBean(boyFriend)的doGetBean方法

6.dogetbean的getSingleton()方法 这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象

7.createBean()

8.doCreateBean()

9.doCreateBean()里的populateBean方法 准备填充bean实例的属性

现在增加指定条件断点:beanName.equals("boyFriend")||beanName.equals("girlFriend"),boyfriend先执行来了。

spring源码怎么解决循环依赖?


3.具体流程:

1.addSingletonFactory 三级缓存里添加boyfriend

2.populateBean 中 boyfriend 加载 girlfriend addSingletonFactory 三级缓存里添加girlfriend

3.populateBean girlfriend 加载 boyfriend 从三级缓存读取boyfriend 并将其清除,并保存boyfriend到二级缓存

4.至此girlfriend装配完毕,执行到defaultSingletonBeanRegister里的getSingleton方法里的addSingleton方法将装配有boyfriend的girlfriend实例存入一级缓存,并清除二级缓存中的girlfriend,清除三级缓存中的girlfriend

5.至此boyfriend装配完毕,执行到defaultSingletonBeanRegister里的getSingleton方法里的addSingleton方法将装配有girlfriend的boyfriend实例存入一级缓存,并清除二级缓存中的boyfriend,清除三级缓存中的boyfriend

spring源码怎么解决循环依赖?


4.spring对其他循环依赖的情况

1非单例是否支持依赖?

spring不支持多例循环依赖,spring有一个bean正在创建的列表,beanname作为标志,因为名称相同所以抛出循环依赖异常

spring源码怎么解决循环依赖?

2.构造器循环依赖?

spring会把正在创建的单例列表保存起来,当A对象加载的时候,此时保存A到列表,去加载A依赖的B对象,B对象加载的时候,保存B到列表 ,再去加载A ,此时spring发现因为A已经在列表上了,所以抛出循环依赖异常,以为这里没有三级缓存的概念(代码还未执行到三级缓存处)相当于只有一级缓存,所以无法实现循环依赖

上一篇:你还在 new 对象吗?Java8 通用 Builder 了解一下?


下一篇:并发编程之协程