循环依赖是指在N个类中循环嵌套引用。如果这种循环依赖在日常开发中以new对象的形式出现,程序在运行时会不断调用,直到内存溢出报错。下面说说Spring是如何解决循环依赖的。第一种:构造函数参数循环依赖Spring容器会将每一个正在创建的bean标识放在一个“当前创建的bean池”中,在创建过程中bean标识会一直保留在这个池中。因此,如果在创建bean的过程中,发现自己已经在“当前创建的bean池”中,则会抛出BeanCurrentlyInCreationException,表示存在循环依赖;并且创建的bean将从“当前创建的bean池”中清除。首先,我们初始化三个bean。publicclassStudentA{privateStudentBstudentB;publicvoidsetStudentB(StudentBstudentB){this.studentB=studentB;}publicStudentA(){}publicStudentA(StudentBstudentB){this.studentB=studentB;}}publicclassStudentB{privateStudentCstudentC;publicvoidsetStudentC(StudentCstudentC){this.studentC;}publicStudentB(){}publicStudentB(StudentCstudentC){this.studentC=studentC;}}publicclassStudentC{privateStudentAstudentA;publicvoidsetStudentA(StudentAstudentA){this.studentA=studentA;}publicStudentC(){}publicStudentC(StudentAstudentA=thisA)}}好的,以上是三个基础类,StudentA有一个StudentB的参数结构。StudentB的参数化结构是StudentC,StudentC的参数化结构是StudentA,这样就形成了循环依赖。我们把这三个bean都交给Spring管理,用参数化结构实例化。下面是测试类:publicclassTest{publicstaticvoidmain(String[]args){ApplicationContextcontext=newClassPathXmlApplicationContext("com/zfx/student/applicationContext.xml");//System.out.println(context.getBean("a",StudentA.class));}}执行结果报错信息为:Causedby:org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为“a”的bean时出错:请求的beans当前正在增加:Istheran无法解析的循环引用?如果您理解开头的句子,这个错误就不足为奇了。首先是Spring容器创建一个单例StudentA,StudentA依赖StudentB,然后将A放入“当前创建的Bean池”此时创建StudentB,StudentB依赖StudentC,再将B放入“当前创建的Bean池”,创建StudentC于这一次,StudentC又依赖于StudentA。但是,此时Student已经在pool中了,所以会报错,因为pool中的bean还没有初始化,所以会依赖错误,将初始化好的bean从pool中移除。第二种:setter方法单例,默认方法如果要说setter方法注入,我们最好看一张Spring实例化Bean的图,如图中前两步:Spring首先实例化Beanobject设置了对象属性后,为什么Spring中的bean默认为单实例?我建议你阅读这篇文章。关注微信公众号:Java技术栈,后台回复:spring,可以获取我整理的最新Spring教程,都是干货。修改配置文件注入set方法下面是测试类:.getBean("a",StudentA.class));}}打印结果为:com.zfx.student.StudentA@1fbfd6为什么set方法不报错?我们看上图,Spring首先实例化了结构体的Bean对象,此时Spring会使用这个实例完成后的对象放在一个Map中,Spring提供了方法获取尚未设置属性的实例化对象的引用。从我们的示例来看,当Spring实例化StudentA、StudentB和StudentC时,它会随后设置对象的属性。这时候StudentA依赖了StudentB,它会去Map中取出存在于其中的单例StudentB对象。以此类推,就不会有循环的问题。下面是Spring源码中的实现方法。以下源码在SpringBean包中的DefaultSingletonBeanRegistry.java类中Object>(64);/**Cacheofsingletonfactories:beanname-->ObjectFactory(单例工厂Bean缓存集合)*/privatefinalMapsingletonFactories=newHashMap(16);/**Cacheofearlysingletonobjects:beanname-->beaninstance(早期单例对象缓存集合)*/privatefinalMapearlySingletonObjects=newHashMap(16);/**Setofregisteredsingletons,包含注册顺序中的bean名(单例实例化对象名集合)*/privatefinalSetregisteredSingletons=newLinkedHashSet(64);/***添加单例实例*解决循环引用问题*Addthegivensingletonfactoryforbuildingthespecifiedsingleton*ifnecessary.*被称为foreegerregistrationofsingletons,e.g.tobeableto*resolvecircularreferences.*@parambeanNamethenamethename*@paramsingletonFactorythefactoryforthesingletonobject*/protectedvoidaddSingletonFactory(StringbeanName,ObjectFactorysingletonFactory){Assert.notNull(singletonFactory,"Singletonfactorymustnotbenull");同步(this.singletonObjects){if(!this.singletonObjects.containsKey(beanName)){this.singletonName,singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}第三种:setter方式原型,prototype修改配置文件为:scope="prototype"表示每次请求都会创建一个实例对象两者的区别是:statefulbeans使用Prototype作用域,stateless一般singleton单例作用域是used.Testcase:publicclassTest{publicstaticvoidmain(String[]args){ApplicationContextcontext=newClassPathXmlApplicationContext("com/zfx/student/applicationContext.xml");//此时必须获取Spring管理的实例,因为nowscope="prototype"只会在获取到请求时实例化对象:Errorcreatingbeanwithname'a':Requestedbeaniscurrentlyincreation:Istheranunresolvablecircularreference?为什么prototype模式报错?对于“prototype”作用域bean,Spring容器无法完成依赖注入,因为“prototype”作用域bean,Spring包含ner没有Cache,所以没有办法暴露一个正在提前创建的bean。