所谓循环依赖指的是:BeanA对象的创建依赖于BeanB,BeanB对象的创建也依赖于BeanA,这就造成了死循环,如果不做处理的话势必会造成栈溢出。Spring通过提前曝光机制,利用三级缓存解决循环依赖问题。本节将记录单实例Bean的创建过程,并且仅记录两种常见的循环依赖情况:普通Bean与普通Bean之间的循环依赖,普通Bean与代理Bean之间的循环依赖。

Bean创建源码

我们先通过源码熟悉下Bean创建过程(源码仅贴出相关部分)。

IOC容器获取Bean的入口为AbstractBeanFactory类的getBean方法:

  1. public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
  2. ......
  3. @Override
  4. public Object getBean(String name) throws BeansException {
  5. return doGetBean(name, null, null, false);
  6. }
  7. ......
  8. }

该方法是一个空壳方法,具体逻辑都在doGetBean方法内:

  1. public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
  2. ......
  3. protected <T> T doGetBean(
  4. String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
  5. throws BeansException {
  6. // 获取Bean名称
  7. String beanName = transformedBeanName(name);
  8. Object bean;
  9. // 从三级缓存中获取目标Bean实例
  10. Object sharedInstance = getSingleton(beanName);
  11. if (sharedInstance != null && args == null) {
  12. ......
  13. // 不为空,则进行后续处理并返回
  14. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  15. } else {
  16. ......
  17. try {
  18. ......
  19. RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  20. ......
  21. // 从三级缓存中没有获取到Bean实例,并且目标Bean是单实例Bean的话
  22. if (mbd.isSingleton()) {
  23. // 通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建Bean实例
  24. sharedInstance = getSingleton(beanName, () -> {
  25. try {
  26. // 创建Bean实例
  27. return createBean(beanName, mbd, args);
  28. }
  29. catch (BeansException ex) {
  30. ......
  31. }
  32. });
  33. // 后续处理,并返回
  34. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  35. }
  36. ......
  37. }
  38. catch (BeansException ex) {
  39. ......
  40. }
  41. finally {
  42. ......
  43. }
  44. }
  45. ......
  46. return (T) bean;
  47. }
  48. ......
  49. }

doGetBean方法中先通过getSingleton(String beanName)方法从三级缓存中获取Bean实例,如果不为空则进行后续处理;如果为空,则通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建Bean实例并进行后续处理。

这两个方法都是AbstractBeanFactory父类DefaultSingletonBeanRegistry的方法,AbstractBeanFactory层级关系图如下所示:

深入理解Spring循环依赖 - 图1

getSingleton(String beanName)相关源码如下所示:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. ......
  3. @Override
  4. @Nullable
  5. public Object getSingleton(String beanName) {
  6. return getSingleton(beanName, true);
  7. }
  8. ......
  9. @Nullable
  10. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  11. // 从一级缓存中获取目标Bean实例
  12. Object singletonObject = this.singletonObjects.get(beanName);
  13. // 如果从一级缓存中没有获取到,并且该Bean处于正在创建中的状态时
  14. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  15. // 从二级缓存获取目标Bean实例
  16. singletonObject = this.earlySingletonObjects.get(beanName);
  17. // 如果没有获取到,并且允许提前曝光的话
  18. if (singletonObject == null && allowEarlyReference) {
  19. synchronized (this.singletonObjects) {
  20. // 在锁内重新从一级缓存中往下查找
  21. singletonObject = this.singletonObjects.get(beanName);
  22. if (singletonObject == null) {
  23. singletonObject = this.earlySingletonObjects.get(beanName);
  24. if (singletonObject == null) {
  25. // 从三级缓存中取出目标Bean工厂对象
  26. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  27. if (singletonFactory != null) {
  28. // 工厂对象不为空,则通过调用getObject方法实例化Bean实例
  29. singletonObject = singletonFactory.getObject();
  30. // 放到二级缓存中
  31. this.earlySingletonObjects.put(beanName, singletonObject);
  32. // 删除对应的三级缓存
  33. this.singletonFactories.remove(beanName);
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }
  40. return singletonObject;
  41. }
  42. ......

所谓的三级缓存指的是DefaultSingletonBeanRegistry类的三个成员变量:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. /** Cache of singleton objects: bean name to bean instance. */
  3. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  4. /** Cache of singleton factories: bean name to ObjectFactory. */
  5. private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  6. /** Cache of early singleton objects: bean name to bean instance. */
  7. private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  8. ......
  9. }
变量 描述
singletonObjects 一级缓存,key为Bean名称,value为Bean实例。这里的Bean实例指的是已经完全创建好的,即已经经历实例化->属性填充->初始化以及各种后置处理过程的Bean,可直接使用。
earlySingletonObjects 二级缓存,key为Bean名称,value为Bean实例。这里的Bean实例指的是仅完成实例化的Bean,还未进行属性填充等后续操作。用于提前曝光,供别的Bean引用,解决循环依赖。
singletonFactories 三级缓存,key为Bean名称,value为Bean工厂。在Bean实例化后,属性填充之前,如果允许提前曝光,Spring会把该Bean转换成Bean工厂并加入到三级缓存。在需要引用提前曝光对象时再通过工厂对象的getObject()方法获取。

如果通过三级缓存的查找都没有找到目标Bean实例,则通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法创建:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. ......
  3. public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
  4. synchronized (this.singletonObjects) {
  5. // 从一级缓存获取
  6. Object singletonObject = this.singletonObjects.get(beanName);
  7. if (singletonObject == null) {
  8. // 为空则继续
  9. ......
  10. // 方法内会将当前Bean名称添加到正在创建Bean的集合(singletonsCurrentlyInCreation)中
  11. beforeSingletonCreation(beanName);
  12. boolean newSingleton = false;
  13. ......
  14. try {
  15. // 通过函数式接口创建Bean实例,该实例已经经历实例化->属性填充->初始化以及各种后置处理过程,可直接使用
  16. singletonObject = singletonFactory.getObject();
  17. newSingleton = true;
  18. }
  19. catch (IllegalStateException ex) {
  20. ......
  21. }
  22. finally {
  23. ......
  24. }
  25. if (newSingleton) {
  26. // 添加到缓存中
  27. addSingleton(beanName, singletonObject);
  28. }
  29. }
  30. return singletonObject;
  31. }
  32. }
  33. protected void addSingleton(String beanName, Object singletonObject) {
  34. synchronized (this.singletonObjects) {
  35. // 添加到一级缓存
  36. this.singletonObjects.put(beanName, singletonObject);
  37. // 删除对应的二三级缓存
  38. this.singletonFactories.remove(beanName);
  39. this.earlySingletonObjects.remove(beanName);
  40. this.registeredSingletons.add(beanName);
  41. }
  42. }
  43. ......
  44. }

上述代码重点关注singletonFactory.getObject(),singletonFactory是一个函数式接口,对应AbstractBeanFactory的doGetBean方法中的lambda表达式:

  1. sharedInstance = getSingleton(beanName, () -> {
  2. try {
  3. // 创建Bean实例
  4. return createBean(beanName, mbd, args);
  5. }
  6. catch (BeansException ex) {
  7. ......
  8. }
  9. });

重点关注createBean方法。该方法为抽象方法,由AbstractBeanFactory子类AbstractAutowireCapableBeanFactory实现:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  2. implements AutowireCapableBeanFactory {
  3. ......
  4. @Override
  5. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  6. throws BeanCreationException {
  7. ......
  8. try {
  9. // 创建Bean实例
  10. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  11. return beanInstance;
  12. }
  13. catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
  14. ......
  15. }
  16. }
  17. ......
  18. }

doCreateBean源码:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  2. implements AutowireCapableBeanFactory {
  3. ......
  4. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  5. throws BeanCreationException {
  6. BeanWrapper instanceWrapper = null;
  7. ......
  8. // 实例化Bean
  9. if (instanceWrapper == null) {
  10. instanceWrapper = createBeanInstance(beanName, mbd, args);
  11. }
  12. Object bean = instanceWrapper.getWrappedInstance();
  13. ......
  14. synchronized (mbd.postProcessingLock) {
  15. if (!mbd.postProcessed) {
  16. try {
  17. // 执行MergedBeanDefinitionPostProcessor类型后置处理器
  18. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  19. }
  20. catch (Throwable ex) {
  21. ......
  22. }
  23. }
  24. }
  25. // 如果该Bean是单例,并且allowCircularReferences属性为true(标识允许循环依赖的出现)以及该Bean正在创建中
  26. // 的话,earlySingletonExposure就为true,标识允许单实例Bean提前暴露原始对象引用(仅实例化)
  27. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  28. isSingletonCurrentlyInCreation(beanName));
  29. if (earlySingletonExposure) {
  30. // 添加到单实例工厂集合中,即三级缓存对象,该方法第二个参数类型为ObjectFactory<?> singletonFactory,
  31. // 前面提到过,它是一个函数式接口,这里用lambda表达式() -> getEarlyBeanReference(beanName, mbd, bean)表示
  32. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  33. }
  34. Object exposedObject = bean;
  35. try {
  36. // 属性赋值操作
  37. populateBean(beanName, mbd, instanceWrapper);
  38. // 初始化Bean(初始化操作主要包括xxxxAware注入,BeanPostProcessor后置处理器方法调用以
  39. // 及InitializingBean接口方法调用,感兴趣的可以自己查看源码)
  40. exposedObject = initializeBean(beanName, exposedObject, mbd);
  41. }
  42. catch (Throwable ex) {
  43. ......
  44. }
  45. // 如果earlySingletonExposure为true
  46. if (earlySingletonExposure) {
  47. // 第二个参数为false表示仅从一级和二级缓存中获取Bean实例
  48. Object earlySingletonReference = getSingleton(beanName, false);
  49. if (earlySingletonReference != null) {
  50. if (exposedObject == bean) {
  51. // 如果从一级和二级缓存中获取Bean实例不为空,并且exposedObject == bean的话,
  52. // 将earlySingletonReference赋值给exposedObject返回
  53. exposedObject = earlySingletonReference;
  54. }
  55. ......
  56. }
  57. }
  58. ......
  59. // 返回最终Bean实例
  60. return exposedObject;
  61. }
  62. ......
  63. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  64. Object exposedObject = bean;
  65. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  66. // SmartInstantiationAwareBeanPostProcessor类型后置处理,常见的场景为AOP代理
  67. for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
  68. exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
  69. }
  70. }
  71. return exposedObject;
  72. }
  73. }

addSingletonFactory方法为父类DefaultSingletonBeanRegistry的方法:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. ......
  3. protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
  4. synchronized (this.singletonObjects) {
  5. // 一级缓存没有目标Bean实例的话,添加三级缓存
  6. if (!this.singletonObjects.containsKey(beanName)) {
  7. this.singletonFactories.put(beanName, singletonFactory);
  8. this.earlySingletonObjects.remove(beanName);
  9. this.registeredSingletons.add(beanName);
  10. }
  11. }
  12. }
  13. ......
  14. }

上述整个过程可以用下图来总结(可右键选择新标签页中打开图片):

深入理解Spring循环依赖 - 图2

光看源码有点抽象,下面我们通过两个场景来加深理解。

普通Bean与普通Bean

首先模拟普通Spring Bean与普通Spring Bean之间循环依赖的场景。

新建SpringBoot项目,pom引入如下依赖:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter</artifactId>
  5. </dependency>
  6. </dependencies>

新建CircularReferenceTest类:

  1. public class CircularReferenceTest {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanA.class, BeanB.class);
  4. BeanA beanA = context.getBean(BeanA.class);
  5. BeanB beanB = context.getBean(BeanB.class);
  6. BeanB beanBInBeanA = beanA.getBeanB();
  7. BeanA beanAInBeanB = beanB.getBeanA();
  8. System.out.println(beanA);
  9. System.out.println(beanB);
  10. System.out.println(beanB == beanBInBeanA);
  11. System.out.println(beanA == beanAInBeanB);
  12. }
  13. }
  14. class BeanA {
  15. @Autowired
  16. private BeanB beanB;
  17. public BeanB getBeanB() {
  18. return beanB;
  19. }
  20. public void setBeanB(BeanB beanB) {
  21. this.beanB = beanB;
  22. }
  23. }
  24. class BeanB {
  25. @Autowired
  26. private BeanA beanA;
  27. public BeanA getBeanA() {
  28. return beanA;
  29. }
  30. public void setBeanA(BeanA beanA) {
  31. this.beanA = beanA;
  32. }
  33. }

上面代码通过AnnotationConfigApplicationContext创建了IOC容器,并先后注册了BeanA和BeanB,BeanA和BeanB相互依赖,程序输出如下:

  1. cc.mrbird.BeanA@368f2016
  2. cc.mrbird.BeanB@6f03482
  3. true
  4. true

可以看到,Spring成功解决了循环依赖。下面配合源码来分析这个过程。

上面程序中,先创建BeanA,Spring内部调用doGetBean方法获取BeanA。一开始三级缓存中肯定没有BeanA和BeanB相关实例:

深入理解Spring循环依赖 - 图3

深入理解Spring循环依赖 - 图4

深入理解Spring循环依赖 - 图5

所以我们直接看doCreateBean相关源码:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  2. implements AutowireCapableBeanFactory {
  3. ......
  4. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  5. throws BeanCreationException {
  6. BeanWrapper instanceWrapper = null;
  7. ......
  8. // 实例化BeanA,BeanA的早期对象,属性还未赋值,还未进行后置处理
  9. if (instanceWrapper == null) {
  10. instanceWrapper = createBeanInstance(beanName, mbd, args);
  11. }
  12. Object bean = instanceWrapper.getWrappedInstance();
  13. ......
  14. // BeanA是单例对象,并且allowCircularReferences为true,BeanA正在创建中,所以
  15. // 最终earlySingletonExposure为true
  16. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  17. isSingletonCurrentlyInCreation(beanName));
  18. if (earlySingletonExposure) {
  19. // 将BeanA早期对象传递给Bean工厂,并添加到三级缓存中
  20. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  21. }
  22. Object exposedObject = bean;
  23. try {
  24. // 属性赋值操作
  25. populateBean(beanName, mbd, instanceWrapper);
  26. ......
  27. }
  28. ......
  29. }
  30. ......
  31. }

上面代码,Spring实例化了BeanA,然后往三级缓存中添加了BeanA的工厂对象,根据前面getEarlyBeanReference方法的源码我们可以知道,在不存在AOP代理的情况下,该方法直接返回原始BeanA对象。所以通过该工厂方法创建的BeanA对象仅仅是进行了实例化操作,属性还未被赋值,换句话说,该工厂用于提前曝光BeanA实例。

接着调用populateBean方法对BeanA属性赋值,赋值过程发现BeanA依赖于BeanB,所以Spring重复以上步骤创建BeanB。创建过程中同样会遇到populateBean方法对BeanB属性赋值,赋值过程中发现BeanB依赖于BeanA,于是Spring又回头创建BeanA,不过这时候情况就开始不一样了!!

doGetBean方法内部从三级缓存中获取BeanA对象时,三级缓存内容如下:

深入理解Spring循环依赖 - 图6

深入理解Spring循环依赖 - 图7

深入理解Spring循环依赖 - 图8

可以看到一级缓存和二级缓存没有什么不一样,但三级缓存中已经存在BeanA和BeanB的工厂对象了!

所以此时getSingleton(String beanName, boolean allowEarlyReference)方法内的逻辑如下:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. ......
  3. @Nullable
  4. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  5. Object singletonObject = this.singletonObjects.get(beanName);
  6. // 一级缓存中没有BeanA,并且BeanA正在创建中
  7. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  8. singletonObject = this.earlySingletonObjects.get(beanName);
  9. // 二级缓存中也没有BeanA
  10. if (singletonObject == null && allowEarlyReference) {
  11. synchronized (this.singletonObjects) {
  12. // 在锁内重新从一级缓存中往下查找
  13. singletonObject = this.singletonObjects.get(beanName);
  14. if (singletonObject == null) {
  15. singletonObject = this.earlySingletonObjects.get(beanName);
  16. if (singletonObject == null) {
  17. // 从三级缓存中取出目标BeanA的工厂对象
  18. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  19. if (singletonFactory != null) {
  20. // 工厂对象不为空,调用getObject方法获取前面提前曝光的BeanA早期实例
  21. singletonObject = singletonFactory.getObject();
  22. // 将BeanA早期实例放到二级缓存中
  23. this.earlySingletonObjects.put(beanName, singletonObject);
  24. // 删除对应的三级缓存
  25. this.singletonFactories.remove(beanName);
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }
  32. // 返回BeanA早期实例
  33. return singletonObject;
  34. }
  35. ......

此时查看二级缓存:

深入理解Spring循环依赖 - 图9

可以看到,BeanA确实只是早期实例,属性BeanB还未被赋值呢。

随后BeanB在属性填充的时候获取到了BeanA早期实例,完成属性填充、初始化等后续操作,BeanB创建完毕。BeanB完整创建完毕后,BeanA随之也完成属性填充、初始化等后续操作,BeanA也创建完毕,循环依赖得以解决。

BeanB虽然获取到的是BeanA的早期对象,但当BeanA完整创建完毕后,BeanB里的BeanA也将会是完整的,因为指针指向的都是同一个BeanA地址。

画个图总结上面的过程(可右键选择新标签页中打开图片):

深入理解Spring循环依赖 - 图10

普通Bean与代理Bean

普通Bean和代理Bean之间的循环依赖和上面过程差不多,不过细节上有些许差异。

删除上面创建的CircularReferenceTest类。为了模拟AOP代理的情况,我们需要引入AOP依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

然后修改Boot入口类:

  1. @SpringBootApplication
  2. public class MyApplication {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
  5. BeanA beanA = context.getBean(BeanA.class);
  6. BeanB beanB = context.getBean(BeanB.class);
  7. BeanB beanBInBeanA = beanA.getBeanB();
  8. BeanA beanAInBeanB = beanB.getBeanA();
  9. System.out.println("BeanA是否为代理对象:" + AopUtils.isAopProxy(beanA));
  10. System.out.println("BeanB是否为代理对象:" + AopUtils.isAopProxy(beanB));
  11. System.out.println("beanAInBeanB是否为代理对象:" + AopUtils.isAopProxy(beanAInBeanB));
  12. System.out.println(beanB == beanBInBeanA);
  13. System.out.println(beanA == beanAInBeanB);
  14. }
  15. }
  16. @Component
  17. class BeanA {
  18. @Autowired
  19. private BeanB beanB;
  20. public BeanB getBeanB() {
  21. return beanB;
  22. }
  23. public void setBeanB(BeanB beanB) {
  24. this.beanB = beanB;
  25. }
  26. }
  27. @Component
  28. class BeanB {
  29. @Autowired
  30. private BeanA beanA;
  31. public BeanA getBeanA() {
  32. return beanA;
  33. }
  34. public void setBeanA(BeanA beanA) {
  35. this.beanA = beanA;
  36. }
  37. }
  38. @Aspect
  39. @Component
  40. class MyAspect {
  41. @Pointcut("execution(public * cc.mrbird.BeanA.getBeanB())")
  42. public void pointcut() {
  43. }
  44. @Before("pointcut()")
  45. public void onBefore(JoinPoint joinPoint) {
  46. System.out.println("onBefore:" + joinPoint.getSignature().getName() + "方法开始执行");
  47. }
  48. }

因为MyAspect切面类的存在,BeanA将会是个代理类,而BeanB则是普通Bean,程序输出如下:

  1. onBefore:getBeanB方法开始执行
  2. BeanA是否为代理对象:true
  3. BeanB是否为代理对象:false
  4. beanAInBeanB是否为代理对象:true
  5. true
  6. true

假设容器先创建BeanA,过程和上面的例子一致,属性填充时,发现BeanA依赖BeanB,然后Spring开始创建BeanB。创建BeanB时候又发现其依赖BeanA,这时三级缓存中已经存在BeanA的工厂对象了,所以直接通过该工厂对象获取BeanA的早期实例:

  1. public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  2. ......
  3. @Nullable
  4. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  5. Object singletonObject = this.singletonObjects.get(beanName);
  6. // 一级缓存中没有BeanA,并且BeanA正在创建中
  7. if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  8. singletonObject = this.earlySingletonObjects.get(beanName);
  9. // 二级缓存中也没有BeanA
  10. if (singletonObject == null && allowEarlyReference) {
  11. synchronized (this.singletonObjects) {
  12. // 在锁内重新从一级缓存中往下查找
  13. singletonObject = this.singletonObjects.get(beanName);
  14. if (singletonObject == null) {
  15. singletonObject = this.earlySingletonObjects.get(beanName);
  16. if (singletonObject == null) {
  17. // 从三级缓存中取出目标BeanA的工厂对象
  18. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  19. if (singletonFactory != null) {
  20. // 工厂对象不为空,调用getObject方法获取前面提前曝光的BeanA早期实例
  21. singletonObject = singletonFactory.getObject();
  22. // 将BeanA早期实例放到二级缓存中
  23. this.earlySingletonObjects.put(beanName, singletonObject);
  24. // 删除对应的三级缓存
  25. this.singletonFactories.remove(beanName);
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }
  32. // 返回BeanA早期实例
  33. return singletonObject;
  34. }
  35. ......

singletonFactory.getObject()实际实现为lambda表达式() -> getEarlyBeanReference(beanName, mbd, bean),getEarlyBeanReference方法源码:

  1. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
  2. Object exposedObject = bean;
  3. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  4. for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
  5. exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
  6. }
  7. }
  8. return exposedObject;
  9. }

在引入AOP依赖后,容器中将会有一个SmartInstantiationAwareBeanPostProcessor接口的实现类AbstractAutoProxyCreator,用于创建AOP代理,所以上面getEarlyBeanReference方法里的bp.getEarlyBeanReference(exposedObject, beanName)逻辑实际上为AbstractAutoProxyCreator实现的getEarlyBeanReference方法:

  1. public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
  2. implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
  3. @Override
  4. public Object getEarlyBeanReference(Object bean, String beanName) {
  5. // 生成缓存Key
  6. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  7. // 放入earlyProxyReferences集合中,标识BeanA为早期代理对象
  8. this.earlyProxyReferences.put(cacheKey, bean);
  9. // 在这个例子中,BeanA将被包装为代理对象
  10. return wrapIfNecessary(bean, beanName, cacheKey);
  11. }
  12. }

所以BeanB从三级缓存中获取到的为代理后的BeanA实例:

深入理解Spring循环依赖 - 图11

BeanB创建完毕后,BeanA属性填充操作随之结束。

通过深入理解Spring-AOP原理对AOP的学习我们知道,代理对象是在后置处理BeanPostProcessor的postProcessAfterInitialization方法内完成的,而该方法的调用时机为Bean属性填充后的初始化操作时,所以在BeanA属性填充操作结束时,BeanA还只是一个普通对象,而BeanB里的BeanA已经是代理对象了。

继续BeanA的创建过程,BeanA属性填充完后,执行initializeBean(beanName, exposedObject, mbd)方法进行初始化操作:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  2. implements AutowireCapableBeanFactory {
  3. ......
  4. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  5. throws BeanCreationException {
  6. ......
  7. Object exposedObject = bean;
  8. try {
  9. // 属性赋值操作
  10. populateBean(beanName, mbd, instanceWrapper);
  11. // 初始化操作
  12. exposedObject = initializeBean(beanName, exposedObject, mbd);
  13. }
  14. ......
  15. }
  16. ......
  17. }

我们主要关注初始化操作阶段执行动态代理的后置处理方法过程:

  1. public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
  2. implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
  3. ......
  4. @Override
  5. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  6. if (bean != null) {
  7. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  8. // 在BeanB填充属性时,BeanA已经被放入到earlyProxyReferences集合中了
  9. // 所以该if不成立,直接跳过,避免二次代理
  10. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  11. return wrapIfNecessary(bean, beanName, cacheKey);
  12. }
  13. }
  14. // 所以这里返回的还是BeanA原始对象,并非代理对象
  15. return bean;
  16. }
  17. ......

到这里BeanA依旧是普通对象,继续查看doCreateBean方法的后续逻辑:

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
  2. implements AutowireCapableBeanFactory {
  3. ......
  4. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  5. throws BeanCreationException {
  6. ......
  7. // 原始BeanA赋值给exposedObject
  8. Object exposedObject = bean;
  9. try {
  10. // 属性赋值操作
  11. populateBean(beanName, mbd, instanceWrapper);
  12. // 初始化操作,通过上面分析,此时返回的还是原始的BeanA对象
  13. exposedObject = initializeBean(beanName, exposedObject, mbd);
  14. }
  15. ......
  16. if (earlySingletonExposure) {
  17. // 从缓存中获取BeanA,此时二级缓存中已经存在BeanA的代理对象了,所以
  18. // 这里earlySingletonReference为BeanA的代理对象(如下图)
  19. Object earlySingletonReference = getSingleton(beanName, false);
  20. if (earlySingletonReference != null) {
  21. // exposedObject和bean相等,因为BeanA并未在初始化的时候被二次代理
  22. if (exposedObject == bean) {
  23. // 这里将代理对象BeanA赋值给exposedObject
  24. exposedObject = earlySingletonReference;
  25. }
  26. ......
  27. }
  28. }
  29. ......
  30. // 最终返回的exposedObject对象为从二级缓存中获取到的BeanA代理对象
  31. return exposedObject;
  32. }
  33. ......
  34. }

深入理解Spring循环依赖 - 图12

到这里,无论是BeanB里的BeanA,还是IOC容器中的BeanA,都是代理后的BeanA了。

画张图总结下上面的过程(可右键选择新标签页中打开图片):

深入理解Spring循环依赖 - 图13

总结

上面的例子都是基于属性注入的情况,假如存在构造器注入情况下的循环依赖,Spring将没办法解决。这是因为对象的提前曝光时机发生在对象实例化之后,而构造器注入时机为对象实例化时,所以此时还未进行提前曝光操作,循环依赖也就没办法解决了,比如下面这种情况:

  1. @SpringBootApplication
  2. public class MyApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(MyApplication.class, args);
  5. }
  6. }
  7. @Component
  8. class BeanA {
  9. private BeanB beanB;
  10. public BeanA(BeanB beanB) {
  11. this.beanB = beanB;
  12. }
  13. public BeanB getBeanB() {
  14. return beanB;
  15. }
  16. public void setBeanB(BeanB beanB) {
  17. this.beanB = beanB;
  18. }
  19. }
  20. @Component
  21. class BeanB {
  22. private BeanA beanA;
  23. public BeanB(BeanA beanA) {
  24. this.beanA = beanA;
  25. }
  26. public BeanA getBeanA() {
  27. return beanA;
  28. }
  29. public void setBeanA(BeanA beanA) {
  30. this.beanA = beanA;
  31. }
  32. }

程序将抛出如下异常:

  1. ***************************
  2. APPLICATION FAILED TO START
  3. ***************************
  4. Description:
  5. The dependencies of some of the beans in the application context form a cycle:
  6. ┌─────┐
  7. | beanA defined in file [/Users/mrbird/idea workspace/aop-deep-learn/target/classes/cc/mrbird/BeanA.class]
  8. | beanB defined in file [/Users/mrbird/idea workspace/aop-deep-learn/target/classes/cc/mrbird/BeanB.class]
  9. └─────┘

此外,这里讨论了普通Bean与普通Bean之间的循环依赖,代理Bean与普通Bean之间的循环依赖,实际情况还可能存在工厂Bean与普通Bean、代理Bean之间的循环依赖,这种情况比较复杂,本文不讨论,因为就理解Spring解决循环依赖的思想而言,上面两种情况搞清楚了就OK了。