—spring为什么要用多级缓存首先清楚spring中的bean加载过程1.需要spring管理的类分析为beanDefinition2.通过反射实例化对象3.通过反射设置属性4.初始化,调用initMethod等(postConstruct也在这里执行)循环依赖的问题:a依赖b,b依赖a。a实例化后,首先将a放入缓存,然后为a设置属性,在缓存中查找b。如果此时没有找到,则开始创建b。b实例化后放入缓存,需要给a设置属性,此时去缓存中查看a是否设置成功。然后初始化。成功后将b放入一级缓存。这时候a在给自己的属性b设置一个值的时候找到了b,然后设置b。完成属性设置,然后初始化。初始化后,a放入一级缓存。二为什么要用三级缓存来解决代理对象(如aop)的循环依赖问题。示例:a依赖于b,b依赖于a,a和b都由aop增强。首先明确aop的实现是通过postBeanProcess后置处理器,初始化后进行代理操作。使用三级缓存的原因:1.只使用了二级缓存,二级缓存缓存了一个不完整的bean。如果只使用二级缓存,二级缓存缓存了一个不完整的bean,此时a在getb中设置属性的过程中(此时a还没有经过aop的后处理器增强)时间)。有一个问题。2使用二级缓存,二级缓存是工厂方法缓存。如果二级缓存是工厂缓存,则在从缓存中获取时获取aop增强对象。您可以看到从工厂缓存中获取的逻辑。protectedObjectgetEarlyBeanReference(StringbeanName,RootBeanDefinitionmbd,Objectbean){ObjectexposedObject=bean;如果(!mbd.isSynthetic()&&hasInstantiationAwareBeanPostProcessors()){for(BeanPostProcessorbp:getBeanPostProcessors()){if(bpinstanceofSmartInstantiationAwareBeanPostProcessor){exposedObject=ibp.getEarlyBeanReference(exposedObject,beanName);}}}returnexposedObject;}a依赖于b,b依赖于a,c。c也依赖于a。a、b、c是aop增强的。加载开始:实例化a,放入工厂缓存,设置b,实例化b,设置属性,获取a,此时从工厂缓存中获取代理a。由于a还没有被加载,所以不会放入一级缓存。这时b开始设置c,实例化c,设置属性a,然后去工厂缓存中获取对象a。此时获取到的a和b并不是工厂缓存中的对象。问题出现。3使用二级缓存,二级缓存缓存增强bean。这与弹簧加载过程不匹配。spring的加载过程是:实例化、设置属性、初始化、增强。当存在循环引用时,之前的bean不会被增强,放入二级缓存。总结1、2、3,可以看出二级缓存无法用aop解决循环依赖。Spring使用三级缓存。三spring的三级缓存一级缓存singletonObjects缓存加载的bean。二级缓存earlySingletonObjects缓存了从三级缓存中获取的bean,里面的bean还没有加载。L3缓存singletonFactories。缓存一个objectFactory工厂。场景:a依赖b,b依赖a和c,c依赖a。而a,b,c都是aop增强的。加载过程:a被实例化,放入三级工厂缓存,设置属性b,b被实例化,放入三级缓存。b设置属性a,从三级工厂缓存中获取代理对象a,同时将代理a放入二级缓存,然后设置属性c,实例化c放入三级缓存一级缓存,设置属性a,此时代理后从二级缓存中获取的a和b中的a是一个对象,属性a设置成功。c被初始化,然后执行后处理器。进行aop的增强。增强后将agent的c放入一级缓存,删除三级缓存中的c。c加载完毕,b获取c,b设置c成功。b被初始化,然后执行后处理器进行aop增强,将增强后的代理对象b放入一级缓存。删除L3缓存中的b。此时a获取b,设置属性b成功,开始初始化,初始化完成后执行后处理器。在aop的后处理器中,有一个mapearlyProxyReferences,以beanName为key,aop增强的代理对象为value。这时,当后处理器处理对象a时,如果(this.earlyProxyReferences.remove(cacheKey)!=bean){returnwrapIfNecessary(bean,beanName,cacheKey);}}returnbean;}即代理后发现beanName不在代理中。这时候后处理器执行完后,a还是一个未被代理的对象a。这时,a又通过getSingleton从缓存中获取了a。ObjectearlySingletonReference=getSingleton(beanName,false);false表示不从三级缓存中取,只从一级和二级缓存中取。这时候就可以在二级缓存中得到一个。二级缓存中的A也是经过代理后的A。然后将代理的a放入一级缓存。一个被加载。放入一级缓存的过程:addSingleton(beanName,singletonObject);从三级工厂缓存中获取对象:protectedObjectgetEarlyBeanReference(StringbeanName,RootBeanDefinitionmbd,Objectbean){ObjectexposedObject=bean;如果(!mbd.isSynthetic()&&hasInstantiationAwareBeanPostProcessors()){for(BeanPostProcessorbp:getBeanPostProcessors()){if(bpinstanceofSmartInstantiationAwareBeanPostProcessor){SmartInstantiationAwareBeanPostProcessoribp=(SmartInstantiationAwareBeanPostProcessor)bp;exposedObject=ibp.getEarlyBeanReference(exposedObject,beanName);}}}returnexposedObject;}其中AbstractAutoProxyCreator实现这个接口。publicObjectgetEarlyBeanReference(Objectbean,StringbeanName){ObjectcacheKey=getCacheKey(bean.getClass(),beanName);this.earlyProxyReferences.put(cacheKey,bean);returnwrapIfNecessary(bean,beanName,cacheKey);}wrapIfNecessary()是代理的实际执行。bean初始化后执行的后处理器:AbstractAutoProxyCreator实现了这个接口。
