1、什么是循环依赖? 循环依赖主要来次三个方面,第一种A相互依赖,第二种是A依赖B,B依赖A,第三种是A依赖B,B依赖C,C依赖A。 总结一句话就是对象之间形成环形依赖。 代码如下: 第一种:publicclassA{privateAa;} 第二种:publicclassA{privateBb;}classB{privateAa;} 第三种:publicclassA{privateBb;}classB{privateCc;}classC{privateAa;}2、Spring三级缓存是什么?第一级缓存:singletonObjects,用于缓存成品的bean,保证Spring的单例属性。第二级缓存:earlySingletonObjects,用于保存实例化完成的半成品bean实例,包括AOP代理对象。第三级缓存:singletonFactories,MapString,ObjectF?,Map的Value是一个对象的代理工厂,用来存放对象的代理工厂用于保存bean创建工厂,以便后面有机会创建代理对象。为打破循环而生,存放的是生成半成品单例Bean的工厂方法。 要想说清楚三级缓存,我们先来看Springbean的生命周期,看bean的创建过程。 核心几个类我们从AnnotationConfigApplicationContext上下文为基础来讲解bean的生命周期,AnnotationConfigApplicationContext是基于注解的上下文,看下这核心构造器。CreateanewAnnotationConfigApplicationContext,derivingbeandefinitionsfromthegivencomponentclassesandautomaticallyrefreshingthecontext。paramcomponentClassesoneormorecomponentclassesforexample,{linkConfigurationConfiguration}classespublicAnnotationConfigApplicationContext(C?。。。componentClasses){this();register(componentClasses);refresh();} 再看refresh()publicvoidrefresh()throwsBeansException,IllegalStateException{synchronized(this。startupShutdownMonitor){StartupStepcontextRefreshthis。applicationStartup。start(spring。context。refresh);Preparethiscontextforrefreshing。prepareRefresh();Tellthesubclasstorefreshtheinternalbeanfactory。ConfigurableListableBeanFactorybeanFactoryobtainFreshBeanFactory();Preparethebeanfactoryforuseinthiscontext。prepareBeanFactory(beanFactory);try{Allowspostprocessingofthebeanfactoryincontextsubclasses。postProcessBeanFactory(beanFactory);StartupStepbeanPostProcessthis。applicationStartup。start(spring。context。beans。postprocess);Invokefactoryprocessorsregisteredasbeansinthecontext。invokeBeanFactoryPostProcessors(beanFactory);Registerbeanprocessorsthatinterceptbeancreation。registerBeanPostProcessors(beanFactory);beanPostProcess。end();Initializemessagesourceforthiscontext。initMessageSource();Initializeeventmulticasterforthiscontext。initApplicationEventMulticaster();Initializeotherspecialbeansinspecificcontextsubclasses。onRefresh();Checkforlistenerbeansandregisterthem。registerListeners();Instantiateallremaining(nonlazyinit)singletons。finishBeanFactoryInitialization(beanFactory);Laststep:publishcorrespondingevent。finishRefresh();}catch(BeansExceptionex){if(logger。isWarnEnabled()){logger。warn(Exceptionencounteredduringcontextinitializationcancellingrefreshattempt:ex);}Destroyalreadycreatedsingletonstoavoiddanglingresources。destroyBeans();Resetactiveflag。cancelRefresh(ex);Propagateexceptiontocaller。}finally{ResetcommonintrospectioncachesinSpringscore,sincewemightnoteverneedmetadataforsingletonbeansanymore。。。resetCommonCaches();contextRefresh。end();}}} 核心主要是finishBeanFactoryInitialization(),其中beanFactory。preInstantiateSingletons()该方法中会生成所有非懒加载的单例bean。protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactorybeanFactory){Initializeconversionserviceforthiscontext。if(beanFactory。containsBean(CONVERSIONSERVICEBEANNAME)beanFactory。isTypeMatch(CONVERSIONSERVICEBEANNAME,ConversionService。class)){beanFactory。setConversionService(beanFactory。getBean(CONVERSIONSERVICEBEANNAME,ConversionService。class));}RegisteradefaultembeddedvalueresolverifnoBeanFactoryPostProcessor(suchasaPropertySourcesPlaceholderConfigurerbean)registeredanybefore:atthispoint,primarilyforresolutioninannotationattributevalues。if(!beanFactory。hasEmbeddedValueResolver()){beanFactory。addEmbeddedValueResolver(strValgetEnvironment()。resolvePlaceholders(strVal));}InitializeLoadTimeWeaverAwarebeansearlytoallowforregisteringtheirtransformersearly。String〔〕weaverAwareNamesbeanFactory。getBeanNamesForType(LoadTimeWeaverAware。class,false,false);for(StringweaverAwareName:weaverAwareNames){getBean(weaverAwareName);}StopusingthetemporaryClassLoaderfortypematching。beanFactory。setTempClassLoader(null);Allowforcachingallbeandefinitionmetadata,notexpectingfurtherchanges。beanFactory。freezeConfiguration();Instantiateallremaining(nonlazyinit)singletons。beanFactory。preInstantiateSingletons();}publicvoidpreInstantiateSingletons()throwsBeansException{if(logger。isTraceEnabled()){logger。trace(Preinstantiatingsingletonsinthis);}Iterateoveracopytoallowforinitmethodswhichinturnregisternewbeandefinitions。Whilethismaynotbepartoftheregularfactorybootstrap,itdoesotherwiseworkfine。ListStringbeanNamesnewArrayList(this。beanDefinitionNames);Triggerinitializationofallnonlazysingletonbeans。。。for(StringbeanName:beanNames){RootBeanDefinitionbdgetMergedLocalBeanDefinition(beanName);if(!bd。isAbstract()bd。isSingleton()!bd。isLazyInit()){if(isFactoryBean(beanName)){ObjectbeangetBean(FACTORYBEANPREFIXbeanName);if(beaninstanceofFactoryBean){FactoryB?factory(FactoryB?)booleanisEagerIif(System。getSecurityManager()!nullfactoryinstanceofSmartFactoryBean){isEagerInitAccessController。doPrivileged((PrivilegedActionBoolean)((SmartFactoryB?)factory)::isEagerInit,getAccessControlContext());}else{isEagerInit(factoryinstanceofSmartFactoryBean((SmartFactoryB?)factory)。isEagerInit());}if(isEagerInit){getBean(beanName);}}}else{getBean(beanName);}}}Triggerpostinitializationcallbackforallapplicablebeans。。。for(StringbeanName:beanNames){ObjectsingletonInstancegetSingleton(beanName);if(singletonInstanceinstanceofSmartInitializingSingleton){StartupStepsmartInitializethis。getApplicationStartup()。start(spring。beans。smartinitialize)。tag(beanName,beanName);SmartInitializingSingletonsmartSingleton(SmartInitializingSingleton)singletonIif(System。getSecurityManager()!null){AccessController。doPrivileged((PrivilegedActionObject)(){smartSingleton。afterSingletonsInstantiated();},getAccessControlContext());}else{smartSingleton。afterSingletonsInstantiated();}smartInitialize。end();}}} doGetBean方法中有getSingleton、getObjectForBeanInstance、createBean比较核心,下面继续看下这代码。代码篇幅过长、简单理解下,在doGetBean方法中首先调用getSingleton方法检查单例缓存中是否有该bean,这也是我们分析三级缓存的关键,如果没有则判断当前bean的作用域是单例(singleton)还是原型(prototype),如果是单例的,再次调用getSingleton方法,不过这次的该方法是重载的一个;如果是原型的则调用createBean方法生成bean,上面几个步骤生成的beanInstance均要调用getObjectForBeanInstance方法获得bean对象。protectedTTdoGetBean(Stringname,NullableClassTrequiredType,NullableObject〔〕args,booleantypeCheckOnly)throwsBeansException{StringbeanNametransformedBeanName(name);ObjectbeanIEagerlychecksingletoncacheformanuallyregisteredsingletons。ObjectsharedInstancegetSingleton(beanName);if(sharedInstance!nullargsnull){if(logger。isTraceEnabled()){if(isSingletonCurrentlyInCreation(beanName)){logger。trace(ReturningeagerlycachedinstanceofsingletonbeanbeanNamethatisnotfullyinitializedyetaconsequenceofacircularreference);}else{logger。trace(ReturningcachedinstanceofsingletonbeanbeanName);}}beanInstancegetObjectForBeanInstance(sharedInstance,name,beanName,null);}else{Failifwerealreadycreatingthisbeaninstance:Wereassumablywithinacircularreference。if(isPrototypeCurrentlyInCreation(beanName)){thrownewBeanCurrentlyInCreationException(beanName);}Checkifbeandefinitionexistsinthisfactory。BeanFactoryparentBeanFactorygetParentBeanFactory();if(parentBeanFactory!null!containsBeanDefinition(beanName)){Notfoundcheckparent。StringnameToLookuporiginalBeanName(name);if(parentBeanFactoryinstanceofAbstractBeanFactory){return((AbstractBeanFactory)parentBeanFactory)。doGetBean(nameToLookup,requiredType,args,typeCheckOnly);}elseif(args!null){Delegationtoparentwithexplicitargs。return(T)parentBeanFactory。getBean(nameToLookup,args);}elseif(requiredType!null){NoargsdelegatetostandardgetBeanmethod。returnparentBeanFactory。getBean(nameToLookup,requiredType);}else{return(T)parentBeanFactory。getBean(nameToLookup);}}if(!typeCheckOnly){markBeanAsCreated(beanName);}StartupStepbeanCreationthis。applicationStartup。start(spring。beans。instantiate)。tag(beanName,name);try{if(requiredType!null){beanCreation。tag(beanType,requiredType::toString);}RootBeanDefinitionmbdgetMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd,beanName,args);Guaranteeinitializationofbeansthatthecurrentbeandependson。String〔〕dependsOnmbd。getDependsOn();if(dependsOn!null){for(Stringdep:dependsOn){if(isDependent(beanName,dep)){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,CirculardependsonrelationshipbetweenbeanNameanddep);}registerDependentBean(dep,beanName);try{getBean(dep);}catch(NoSuchBeanDefinitionExceptionex){thrownewBeanCreationException(mbd。getResourceDescription(),beanName,beanNamedependsonmissingbeandep,ex);}}}Createbeaninstance。if(mbd。isSingleton()){sharedInstancegetSingleton(beanName,(){try{returncreateBean(beanName,mbd,args);}catch(BeansExceptionex){Explicitlyremoveinstancefromsingletoncache:Itmighthavebeenputthereeagerlybythecreationprocess,toallowforcircularreferenceresolution。Alsoremoveanybeansthatreceivedatemporaryreferencetothebean。destroySingleton(beanName);}});beanInstancegetObjectForBeanInstance(sharedInstance,name,beanName,mbd);}elseif(mbd。isPrototype()){Itsaprototypecreateanewinstance。ObjectprototypeItry{beforePrototypeCreation(beanName);prototypeInstancecreateBean(beanName,mbd,args);}finally{afterPrototypeCreation(beanName);}beanInstancegetObjectForBeanInstance(prototypeInstance,name,beanName,mbd);}else{StringscopeNamembd。getScope();if(!StringUtils。hasLength(scopeName)){thrownewIllegalStateException(NoscopenamedefinedforbeanbeanName);}Scopescopethis。scopes。get(scopeName);if(scopenull){thrownewIllegalStateException(NoScoperegisteredforscopenamescopeName);}try{ObjectscopedInstancescope。get(beanName,(){beforePrototypeCreation(beanName);try{returncreateBean(beanName,mbd,args);}finally{afterPrototypeCreation(beanName);}});beanInstancegetObjectForBeanInstance(scopedInstance,name,beanName,mbd);}catch(IllegalStateExceptionex){thrownewScopeNotActiveException(beanName,scopeName,ex);}}}catch(BeansExceptionex){beanCreation。tag(exception,ex。getClass()。toString());beanCreation。tag(message,String。valueOf(ex。getMessage()));cleanupAfterBeanCreationFailure(beanName);}finally{beanCreation。end();}}returnadaptBeanInstance(name,beanInstance,requiredType);} 我们知道了DefaultSingletonBeanRegistry类下的getSingleton是Springbean缓存的关键,那么看下代码,Returnthe(raw)singletonobjectregisteredunderthegivenname。pChecksalreadyinstantiatedsingletonsandalsoallowsforanearlyreferencetoacurrentlycreatedsingleton(resolvingacircularreference)。parambeanNamethenameofthebeantolookforparamallowEarlyReferencewhetherearlyreferencesshouldbecreatedornotreturntheregisteredsingletonobject,or{codenull}ifnonefoundNullableprotectedObjectgetSingleton(StringbeanName,booleanallowEarlyReference){Quickcheckforexistinginstancewithoutfullsingletonlock一级缓存ObjectsingletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnullisSingletonCurrentlyInCreation(beanName)){二级缓存singletonObjectthis。earlySingletonObjects。get(beanName);if(singletonObjectnullallowEarlyReference){synchronized(this。singletonObjects){ConsistentcreationofearlyreferencewithinfullsingletonlocksingletonObjectthis。singletonObjects。get(beanName);if(singletonObjectnull){singletonObjectthis。earlySingletonObjects。get(beanName);if(singletonObjectnull){三级缓存ObjectF?singletonFactorythis。singletonFactories。get(beanName);if(singletonFactory!null){singletonObjectsingletonFactory。getObject();this。earlySingletonObjects。put(beanName,singletonObject);this。singletonFactories。remove(beanName);}}}}}}returnsingletonO} 以上就是从源码上了解三级缓存,执行流程:1。先从第一级缓存找对象,有就返回,没有就找二级缓存; 2。找二级缓存,有就返回,没有就找三级缓存; 3。找三级缓存,找到了,就获取对象,放到二级缓存,从三级缓存移除。3、如何解决缓存依赖问题? 以上都是SpringBean缓存的介绍,是如何解决循环依赖的问题呢? 我们再看一段代码protectedvoidaddSingletonFactory(StringbeanName,ObjectF?singletonFactory){Assert。notNull(singletonFactory,Singletonfactorymustnotbenull);synchronized(this。singletonObjects){判断一级缓存中不存在此对象if(!this。singletonObjects。containsKey(beanName)){直接从工厂中获取BeanobjectosingletonFactory。getObject();添加至二级缓存中this。earlySingletonObjects。put(beanName,o);this。registeredSingletons。add(beanName);}}} 总结来说,Spring通过三级缓存实现循环依赖,来存放对象的代理工厂用于保存bean创建工厂。在遇到循环依赖时候优先通过二级缓存看是否存在依赖对象的半成品、没有则去三级缓存获取BeanFactory创建对象,创建成功之后放入到二级缓存中。 为什么多出二级缓存呢,只要三级缓存能不能实现? 二级缓存的目的是为了避免因为AOP创建多个对象,其中存储的是半成品的AOP的单例bean。 能不能只要二级缓存,二级缓存也可以解决循环依赖问题啊? 主要解决代理对象问题,假如不存在代理对象,二级缓存也是足够的。 Spring只用二级缓存来解决循环依赖,那么所有Bean都需要在实例化完成之后就立马为其创建代理,而Spring的设计原则是会在完成属性填充、并且执行完初始化之后再为其创建代理。所以,Spring选择了三级缓存,,但是因为循环依赖的出现,导致了Spring不得不提前去创建代理,因为如果不提前创建代理对象,那么注入的就是原始对象,这样就会产生错误。