设为首页 - 加入收藏 平凉站长网 (http://www.0933zz.com)- 国内知名站长资讯网站,提供最新最全的站长资讯,创业经验,网站建设等!
热搜: 什么 为什么 平台 赚钱
当前位置: 首页 > 综合聚焦 > 移动互联 > 评测 > 正文

Springboot源码分析之Spring循环依赖揭秘

发布时间:2019-09-13 00:29 所属栏目:[评测] 来源:佚名
导读:摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效。或许刚说到这,有的小伙伴就会大惊失色了。 Spring 不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我们一起揭秘 Spring 循环依赖的最本质原因。 S

摘要:

若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效。或许刚说到这,有的小伙伴就会大惊失色了。?Spring?不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我们一起揭秘?Spring?循环依赖的最本质原因。

Spring循环依赖流程图

Springboot源码分析之Spring循环依赖揭秘

Spring循环依赖发生原因

  • 使用了具有代理特性的BeanPostProcessor
  • 典型的有 事务注解@Transactional,异步注解@Async等?

Springboot源码分析之Spring循环依赖揭秘

Springboot源码分析之Spring循环依赖揭秘

Springboot源码分析之Spring循环依赖揭秘

源码分析揭秘

  1. protected?Object?doCreateBean(?...?){?
  2. ????????...?
  3. ????????boolean?earlySingletonExposure?=?(mbd.isSingleton()?&&?this.allowCircularReferences?&&?isSingletonCurrentlyInCreation(beanName));?
  4. ????????if?(earlySingletonExposure)?{?
  5. ????????????addSingletonFactory(beanName,?()?->?getEarlyBeanReference(beanName,?mbd,?bean));?
  6. ????????}?
  7. ????????...?
  8. ?????
  9. ????????//?populateBean这一句特别的关键,它需要给A的属性赋值,所以此处会去实例化B~~?
  10. ????????//?而B我们从上可以看到它就是个普通的Bean(并不需要创建代理对象),实例化完成之后,继续给他的属性A赋值,而此时它会去拿到A的早期引用?
  11. ????????//?也就在此处在给B的属性a赋值的时候,会执行到上面放进去的Bean?A流程中的getEarlyBeanReference()方法??从而拿到A的早期引用~~?
  12. ????????//?执行A的getEarlyBeanReference()方法的时候,会执行自动代理创建器,但是由于A没有标注事务,所以最终不会创建代理,so?B合格属性引用会是A的**原始对象**?
  13. ????????//?需要注意的是:@Async的代理对象不是在getEarlyBeanReference()中创建的,是在postProcessAfterInitialization创建的代理?
  14. ????????//?从这我们也可以看出@Async的代理它默认并不支持你去循环引用,因为它并没有把代理对象的早期引用提供出来~~~(注意这点和自动代理创建器的区别~)?
  15. ?????
  16. ????????//?结论:此处给A的依赖属性字段B赋值为了B的实例(因为B不需要创建代理,所以就是原始对象)?
  17. ????????//?而此处实例B里面依赖的A注入的仍旧为Bean?A的普通实例对象(注意??是原始对象非代理对象)??注:此时exposedObject也依旧为原始对象?
  18. ????????populateBean(beanName,?mbd,?instanceWrapper);?
  19. ?????????
  20. ????????//?标注有@Async的Bean的代理对象在此处会被生成~~~?参照类:AsyncAnnotationBeanPostProcessor?
  21. ????????//?所以此句执行完成后??exposedObject就会是个代理对象而非原始对象了?
  22. ????????exposedObject?=?initializeBean(beanName,?exposedObject,?mbd);?
  23. ?????????
  24. ????????...?
  25. ????????//?这里是报错的重点~~~?
  26. ????????if?(earlySingletonExposure)?{?
  27. ????????????//?上面说了A被B循环依赖进去了,所以此时A是被放进了二级缓存的,所以此处earlySingletonReference?是A的原始对象的引用?
  28. ????????????//?(这也就解释了为何我说:如果A没有被循环依赖,是不会报错不会有问题的???因为若没有循环依赖earlySingletonReference?=null后面就直接return了)?
  29. ????????????Object?earlySingletonReference?=?getSingleton(beanName,?false);?
  30. ????????????if?(earlySingletonReference?!=?null)?{?
  31. ????????????????//?上面分析了exposedObject?是被@Aysnc代理过的对象,?而bean是原始对象?所以此处不相等??走else逻辑?
  32. ????????????????if?(exposedObject?==?bean)?{?
  33. ????????????????????exposedObject?=?earlySingletonReference;?
  34. ????????????????}?
  35. ????????????????//?allowRawInjectionDespiteWrapping?标注是否允许此Bean的原始类型被注入到其它Bean里面,即使自己最终会被包装(代理)?
  36. ????????????????//?默认是false表示不允许,如果改为true表示允许,就不会报错啦。这是我们后面讲的决方案的其中一个方案~~~?
  37. ????????????????//?另外dependentBeanMap记录着每个Bean它所依赖的Bean的Map~~~~?
  38. ????????????????else?if?(!this.allowRawInjectionDespiteWrapping?&&?hasDependentBean(beanName))?{?
  39. ????????????????????//?我们的Bean?A依赖于B,so此处值为["b"]?
  40. ????????????????????String[]?dependentBeans?=?getDependentBeans(beanName);?
  41. ????????????????????Set?actualDependentBeans?=?new?LinkedHashSet<>(dependentBeans.length);?
  42. ?????
  43. ????????????????????//?对所有的依赖进行一一检查~????比如此处B就会有问题?
  44. ????????????????????//?“b”它经过removeSingletonIfCreatedForTypeCheckOnly最终返返回false??因为alreadyCreated里面已经有它了表示B已经完全创建完成了~~~?
  45. ????????????????????//?而b都完成了,所以属性a也赋值完成儿聊?但是B里面引用的a和主流程我这个A竟然不相等,那肯定就有问题(说明不是最终的)~~~?
  46. ????????????????????//?so最终会被加入到actualDependentBeans里面去,表示A真正的依赖~~~?
  47. ????????????????????for?(String?dependentBean?:?dependentBeans)?{?
  48. ????????????????????????if?(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))?{?
  49. ????????????????????????????actualDependentBeans.add(dependentBean);?
  50. ????????????????????????}?
  51. ????????????????????}?
  52. ?????????
  53. ????????????????????//?若存在这种真正的依赖,那就报错了~~~??则个异常就是上面看到的异常信息?
  54. ????????????????????if?(!actualDependentBeans.isEmpty())?{?
  55. ????????????????????????throw?new?BeanCurrentlyInCreationException(beanName,?
  56. ????????????????????????????????"Bean?with?name?'"?+?beanName?+?"'?has?been?injected?into?other?beans?["?+?
  57. ????????????????????????????????StringUtils.collectionToCommaDelimitedString(actualDependentBeans)?+?
  58. ????????????????????????????????"]?in?its?raw?version?as?part?of?a?circular?reference,?but?has?eventually?been?"?+?
  59. ????????????????????????????????"wrapped.?This?means?that?said?other?beans?do?not?use?the?final?version?of?the?"?+?
  60. ????????????????????????????????"bean.?This?is?often?the?result?of?over-eager?type?matching?-?consider?using?"?+?
  61. ????????????????????????????????"'getBeanNamesOfType'?with?the?'allowEagerInit'?flag?turned?off,?for?example.");?
  62. ????????????????????}?
  63. ????????????????}?
  64. ????????????}?
  65. ????????}?
  66. ????????...?
  67. ????}?

问题简化

  • 发生循环依赖时候?Object earlySingletonReference = getSingleton(beanName, false);?肯定有值
  • 缓存工厂?addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));?将给实例对象添加?SmartInstantiationAwareBeanPostProcessor
  • AbstractAutoProxyCreator?是?SmartInstantiationAwareBeanPostProcessor?的子类,一定记住了,一定记住,?SmartInstantiationAwareBeanPostProcessor?的子类很关键!!!!!
  • exposedObject = initializeBean(beanName, exposedObject, mbd);?进行?BeanPostProcessor后置处理,注意是?BeanPostProcessor?!!!!!

【免责声明】本站内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

网友评论
推荐文章