统计局网站建设情况千万不要做手游推广员
统计局网站建设情况,千万不要做手游推广员,西安公司网页制作,做网站打电话怎么和客户说目录 前置知识循环依赖的产生Spring里面的3个Map 课程内容一、只有一级缓存的推理演进1.1 直接将实例化后生成的对象放入到单例池里面1.1 引入一个中间Map存实例化后的早期对象#xff08;疑似二级缓存#xff09;1.3 解决1.2需要被代理的问题#xff08;疑似二级缓存#… 目录 前置知识循环依赖的产生Spring里面的3个Map 课程内容一、只有一级缓存的推理演进1.1 直接将实例化后生成的对象放入到单例池里面1.1 引入一个中间Map存实例化后的早期对象疑似二级缓存1.3 解决1.2需要被代理的问题疑似二级缓存1.4 为什么要三级缓存 学习总结 前置知识
循环依赖的产生
说到循环依赖大家都不陌生循环依赖的代码就是如下
Component
public class CircularA {AutowiredCircularB b;
}Component
public class CircularB {AutowiredCircularA a;
}
但是大家有没有想过循环依赖是如何产生的然后又是怎么解决的呢这里我想给大家推演一下就像咱是Spring作者一样思考如何循环依赖。
Spring里面的3个Map
在这里我还是想提前给大家先大概解释一下在获取单例bean的时候Spring源码出现的3个Map。分别如下
MapString, Object singletonObjects一级缓存。这个就是我们常说的单例池这里存放的bean是经历了完整Spring生命周期的【走完了Spring所设计的生命周期】这里的经历完整生命周期不是说非得要经历什么实例化前后、初始化前后。简单说是Spring认可的成熟的BeanMapString, Object earlySingletonObjects二级缓存。直接直译过来这里存的是【早期单例Bean】。何为早期就是相对前面的【成熟Bean】【还没有走完生命周期】的Bean。MapString, ObjectFactory? singletonFactories三级缓存。直译过来是【单例bean的工厂】。其实我还是喜欢用一个之前提到过的专有名词去解释生产Bean的钩子方法缓存。
课程内容
一、只有一级缓存的推理演进
我们先来看个图在没有三级缓存之前只有一个一级缓存的时候如果A依赖了BB依赖了A那么就会造成下面的现象 很显然在我们刚开创建的过程中单例池里面是不会有对象B也不会有对象A的。毕竟它们才走到第二步【注入属性】它是在最后一步才会把生成好的对象放入单例池中。所以上图的情况如果没有外部干预的话在这两个bean之间就形成了一个闭环无法解开了。这显然不是我们想要的结果对吧。那这个问题该如何解决呢
1.1 直接将实例化后生成的对象放入到单例池里面
这时候一个很正常的想法是我提前放入到单例池里面不就行了吗如下所示 这样不就打破了吗嘿嘿嘿 只能说有点道理但不多。因为在多线程环境下可能会把【没初始化完】的bean暴露出去。这时候如果有人来访问单例池直接拿到了这个BeanA然后去调用里面的方法在没有【属性注入】过的情况下不就G了吗是的这就是并发安全问题这里只能直接pass这个方案了
1.1 引入一个中间Map存实例化后的早期对象疑似二级缓存
一个很正常的思考我新增一个Map在实例化后即刻存起来不就得了呗。反正都已经实例化了地址已经固定了后面再怎么操作都是对这个地址上的对象操作提前把这个对象暴露出去完全不影响结果啊。 如上图所示那我新增一个中间缓存Map来存储之前实例化后的对象总可以吧嗯从流程图上来看这个真的好像是最终答案了。 不过如果这时候我问你【AOP在哪】阁下将如何应对呢很显然啊这里存放的是原始对象那如果我需要的是被代理的对象呢看吧这样稍微一推敲又出现问题了。那好我们继续完善这个方案就是了
1.3 解决1.2需要被代理的问题疑似二级缓存 就这样多加上一步AOP过程不就行了嘛嘿嘿嘿。不过按照惯例我已经【嘿嘿嘿】了所以肯定得问一句真的行吗哈真的行确实没问题了。那为什么还要三级缓存呢
1.4 为什么要三级缓存
讲到这里我就要开始装逼了。我甚至怀疑Spring这么写也是在【装逼】哈哈开个玩笑 其实这个网上挺多论调的我也是总结了百家之长再结合我课堂上老师说的总结出了以下结论算是个人之见大家参考一下
生命周期被打破这个我认为是最重要的原因但是也比较难被理解的一点。怎么理解呢大家还记得我以开始怎么形容Spring的吗Spring的核心是什么大家知道AOP的实现是在一块吗 第一个问题Spring是实现了AOP技术的IOC容器第二个问题Spring的核心是IOC跟AOP但是所有的基础都来自于IOC第三个问题AOP的实现是在bean生命周期的【初始化后】阶段。因为AOP技术目前的实现也是基于Spring提供的众多拓展点里面的某些个而已。比如AOP的实现就使用了BeanPostProcessor。这里透露出来的意思是什么呢我认为它的意思是在Spring内部都只是把AOP当作额外拓展而已。就好像是我们基于Spring的拓展点实现了Mybatis实现了SpringMVC一样的道理。 PS所以到了这里大家伙知道这个【生命周期被打破】如何理解了吗如果我们在实例化后就做判断是否需要做AOP的话等于还没【属性注入】还没做【初始化前】、【初始化】、【初始化后】等等生命周期呢就要开始了。并且呀在实现这个AOP的过程中你还得调用类似如下的方法 for(BeanPostProcessor bp : this.beanPostProcessorsCache) {bp.postProcessAfterInitialization(bean);
}但是这个代码其实在后面的【初始化后】也会被调用的。我猜有的朋友会这么说那我循环遍历实现了AOP的那几个指定的实现了AOP的BeanPostProcessor不就行了吗嗯说实在确实行。不过如果我们站在Spring的角度来看AOP不过也是我IOC的一个拓展内容而已。这么来看的话这么实现就侵入有点大了而且语义上也稍微变了。 循环依赖出现频率。我想我呢问大家你在实际使用场景中循环依赖出现的多吗弟弟我写Java代码4年多我印象中就几次而已。so你看看上面的解决方案如何它每一次实例化生成Bean之后都做了判断是否有点多余呢代码风格说这个就很抽象了但是对于Spring这种优秀的源码来说又有点情有可原。这句话怎么理解呢
其实2、3要结合起来一起建立在【1】最后的挣扎上即我还是要在【实例化】完成后就开始判断是否需要AOP。
学习总结
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88160.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!