这里先创建2个bean,互相注入,看看spring是怎么解决这个问题的
@Repository public class BoyFriend { @Autowired private GirlFriend girlFriend; }
@Repository public class GirlFriend { @Autowired private BoyFriend boyFriend; }
在populateBean打上断点,可以发现调用栈
一步步分析:
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先执行来了。
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不支持多例循环依赖,spring有一个bean正在创建的列表,beanname作为标志,因为名称相同所以抛出循环依赖异常
spring会把正在创建的单例列表保存起来,当A对象加载的时候,此时保存A到列表,去加载A依赖的B对象,B对象加载的时候,保存B到列表 ,再去加载A ,此时spring发现因为A已经在列表上了,所以抛出循环依赖异常,以为这里没有三级缓存的概念(代码还未执行到三级缓存处)相当于只有一级缓存,所以无法实现循环依赖