一.甚么是二级内存
1.二级内存:放置早已调用顺利完成的Bean
2.二级内存:放置成品Bean,既示例化顺利完成未调用的Bean。
3.二级内存:放置bean厂房
二.为甚么是二级内存
二级内存是要的,那个我们没甚么疑点。那为甚么要有二级内存,二级内存主要就是用以化解循环式倚赖的难题。
2.1甚么是循环式倚赖
循环式倚赖即是循环式提及,是三个或数个Bean彼此之间的所持旁人的提及。
举个单纯的范例:
@Service public class AService { @Resource private BService bService; }@Service public class BService { @Resource private AService aService; }AService中倚赖了BService,而BService又倚赖了AService,这种就形成循环式倚赖。
Spring是容许科枫bean展开循环式依赖的。
2.2循环式倚赖的bean转化成业务流程
下面我就带大家从源代码的层面,讲解二级内存是如何化解循环式倚赖难题的。
1.doCreateBean方法会调用createBeanInstance方法来对beanA展开示例化。
2.addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));会将生成代理对象的厂房放入到二级内存。
3.beanA调用populateBean方法,转化成beanB示例。
在转化成beanB示例的过程中,发现beanB倚赖了beanA,需要将beanA加载出来。
会再次对beanA调用doGetBean方法。这时候,getSingleton方法就真正派上用场了。
4.在getSingleton方法中,会将beanA的bean厂房从二级内存中取出来,调用getObject方法,也就是getEarlyBeanReference方法,将返回结果放入二级内存,同时从二级内存移除掉。
5.把不完整的beanA转化成到beanB中
6.beanB执行addSingleton(beanName, singletonObject)方法,那个方法将beanB放入到二级内存,且从二级内存中移除掉。
7.beanA转化成beanB示例。
8.beanA顺利完成属性填充和调用,执行addSingleton(beanName, singletonObject)方法,将BeanA放入到二级内存。
从上面转化成的业务流程,可以看出,如果没放置成品的二级内存,那么循环式倚赖是无法化解的。如果他们在示例化完beanA,立刻创建出代理对象放到二级内存,再填充beanA的属性以及调用,这种也可以正常顺利完成BeanA,BeanB的转化成。这种就省掉了第二级内存。那第二级内存存在的原因是甚么呢?
2.3.第二级内存在的原因
要理清楚,二级内存存在的原因主要就原因有三个,一是因为AOP,二是循环式倚赖。如果没Spring AOP和循环式倚赖,那么就不需要使用二级内存。
他们先看下,不存在循环式倚赖的代理对象是如何生成的?
上图第五步的时候,会调用AbstractAutoProxyCreator类的
postProcessAfterInitialization方法,创建代理对象。对于不涉及到循环式倚赖的bean,会在调用之后,创建代理对象。而对于涉及到循环倚赖的bean,如果没二级内存,在对象示例化后,就要立刻生成其代理对象,这种会影响到bean转化成整个代码的逻辑。增加二级内存,一可以防止循环式倚赖的对象多次被代理;还可以做到循环式提及的bean,在被循环式提及时,代理对象被创建且转化成进去,不涉及到循环式提及的bean,等到调用之后创建代理对象。
喜欢源代码的朋友关注点赞,后续会分享更多干货。