Spring源码最难问题:当Spring AOP遇上循环依赖.docx
《Spring源码最难问题:当Spring AOP遇上循环依赖.docx》由会员分享,可在线阅读,更多相关《Spring源码最难问题:当Spring AOP遇上循环依赖.docx(13页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Spring源码最难问题:当 Spring AOP 遇上循环依赖 前a问:Spring如何解决循环依赖?答:Spring通过提前曝光机制,利用三级缓存解决循环 依赖。再问:Spring通过提前曝光,直接曝光到二级缓存已经 可以解决循环依赖问题了,为什么一定要三级缓存?再细问:如果循环依赖的时候,所有类又都需要Spring AOP自动代理,那Spring如何提前曝光?曝光的是原始 bean还是代理后的bean?这些问题算是Spring源码的压轴题了,如果这些问题都 弄明白,恭喜你顺利结业Spring源码了。就单单对Spring 这一块的理解,不夸张的说可以到达阿里水准了源码分析/小* 4.填充属
2、性*如果Autowired注解属性,那么在上方完成解析后,在这里完成注入Autowiredrivate Inner inner;populateBean(beanName, mbd, instanceWrapper);/5.初始化exposedObject = initializeBean(beanName, exposedObject, mbd);|ch (Throwable ex) il (ex nstnnceof BeanCreationException & beanName.equals(BeanCr|ua(i()iil-.ccplion c i.LclI-kuii.Wimci i)
3、throw (BeanCreationException) ex;|else throw no BeanCreationException(mbd.getResourceDescription。,beanName, Initialization of bean failed, ex);/6.存在提前曝光情况下Object carlySinglctonRcfcrcncc 二 gctSinglcton(bcanNamc, | (c;iSin9h、l()nRclccnic I 7| i 八pi)、cd( )h|ci l hc;in i 1 腐螫够,:| cxp()、cd()bjccl C”L Sin
4、glclonR匕k| else if (!this.allowRawInjectionDespiteWrapping & hasDependentBean(| Siring dependentBeans 二 ge【DependentBeans(beanNanie | SetString actualDependenlBeans = nc LinkedHashSet(dependent 卜 m -, m 隙; | (Siring dependenlBeiin : dcpendenlBenn、)| if (!removeSingletonIfCreatedForTypeCheckOnIy(depe
5、ndentB6an)actual DependentBeans.add(dependentBean);/被依赖检测异|(匕 c I u ” D c p c n d c n B c a n、. i s IS m p l y ( )J,卷懿|throw new B canC u rrc n U y 1 nCcat iu n Ex ccpt i on (bean N a me| Bean with name + beanName + has been injected into other be| StringUtils.coHectionToCommaDelimitedString(actualD
6、ependentBe| in its raw version as part of a circular reference, but has eventualwrapped. This means that said other beans do not use the final versi“bean. This is often the result of over-eager type nialchintj - consideetBeanNamesOfType with the allowEagerlnit flag turned off, fo|这个时候我们需要理清一下3个变量ear
7、lySingletonReference:二级缓存,缓存的是经过提前曝光提前AOP代理的beanbean:这个就是经过了实例化、填充、初始化的beanexposedObject : 这个是经过了 AbstractAutoProxyCreator 的 postProcessAfterlnitialization 处理 过后的bean,但是在其中因为发现当前bean已经被 earlyProxyReferences缓存,所以并没有进行AOP处理, 而是直接跳过,因此还是跟第2点一样的bean 理清这3个变量以后,就会发现,exposedObject = earlySingletonReference
8、;AOP代理过的Bean赋值给了 exposedObject并返回,这时 候用户拿到的bean就是AOP代理过后的bean 了,一切 皆大欢喜了。但是中间还有一个问题!提前曝光的bean在提前引用时 被Spring AOP代理了,但是止匕时的bean只是经过了实例 化的bean,还没有进行Autowire的注入啊!也就是说此 时代理的bean里面自动注入的属性是空的!另外,搜索 公众号Linux就该这样学后台回复“猴子”,获取一份惊喜 礼包。(四)提前AOP代理对象的属性填充、初始化是的,确实在Spring AOP提前代理后没有经过属性填充 和初始化。那么这个代理又是如何保证依赖属性的注入的呢
9、?答案回到Spring AOP最早最早讲的JDK动态代理 上找,JDK动态代理时,会将目标对象target保存在最 后生成的代理$proxy中,当调用$proxy方法时会回调 h.invoke,而h.invoke又会回调目标对象target的原始方 法。因此,其实在Spring AOP动态代理时,原始bean已经被 保存在提前曝光代理中了。而后原始Bean继续完成属性 填充和初始化操作。因为AOP代理$proxy中保存着traget 也就是是原始bean的引用,因此后续原始bean的完善, 也就相当于Spring AOP中的target的完善,这样就保证 了 Spring AOP的属性填充与初
10、始化了!(五)循环依赖遇上Spring AOP图解为了帮助大家理解,这里灵魂画手画张流程图帮助大家 理解首先又bean A, bean B,他们循环依赖注入,同时bean A 还需要被Spring AOP代理,例如事务管理或者日志之类 的操作。原始bean A, bean B图中用a, b表示,而代理 后的bean A我们用aop.a表不。1,袁道从各圾播存中我取beangetSlnglGton(Ba)7翟试从各圾媚存中技取beangetSingletonCb)13.言词2.检冽a是否在创立状态crtlnCreate.contains(a)8.检测b是否在创立状态crtlnCreate.con
11、tainsCb)此时在第的a的工 aFac3.创立前,先将a标记为创立中crtlnCreate.add( a)9创立前,先将b标记为创立中crtlnCreate.addCb)4.实例化bean = createBeanlnstanceCa)10.实例化bean = createBeanlnstanceCb)5.将bean保存到三级缓存中addSinqletonFactoryl 带 a 的工厂);11.将bean保存到三级缓存中addSingtetonFactory(带 b 的工厂);b填充的属性是aop-a而非a6.填充属性发现需变引用BgotBoan(b)12.塌充属性发现需要引用AgotB
12、oan(-a)19.初始化17.初始化21.创立完成,标识a不在创立中 crtlnCreate.removeCa)怕.创立完成,标识b不在创立中 crtlnCreate.remove(b)AB+ b:B+a : AcurrentlylnCreation:正在创立的bean集合;下方简称crtl, ;昂+getA什earlySingletonObjects:二级缓存,缓存提前曝光的实例;下工 setB(B b);4setA(Aa);singletonFactories:三短缓存,缓存提前曝光的工厂,用于生产二级名getBean(b)getBean(b)getBeanCa)看完也算是Spring的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring源码最难问题:当Spring AOP遇上循环依赖 Spring 源码 问题 AOP 遇上 循环 依赖
限制150内