是这样的。一个实习朋友问我关于循环依赖的问题。我跟他讲了Spring内部的三级缓存原理,确定Spring已经解决了这个问题。然后他抛出一道题给我,说错了。好朋友,感觉是想让我查bug你们看吗?@ComponentpublicclassA{privatefinalBb;publicA(finalBb){this.b=b;}publicvoidprint(){System.out.println("ina");}}@ComponentpublicclassB{privatefinalAa;publicB(finalAa){this.a=a;}publicvoidprint(){System.out.println("inb");}}Causedby:org.springframework.beans.factory.UnsatisfiedDependencyException:Errorcreatingbeanwithname'a'definedinfile[C:\soft\code\common\MongodbDataTest\dbDataTest\target\test-classes\com\db\model\A.class]:Unsatisfieddependencyexpressedthroughconstructorparameter0;nestedexceptionisorg.springframework.beans.factory.UnsatisfiedDependencyException:Errorcreatingbeanwithname'b'定义文件[C:\soft\code\common\MongodbDataTest\dbDataTest\target\test-classes\com\db\model\B.class]:Unsatisfieddependencyexpressedthroughconstructorparameter0;嵌套异常isorg.springframework.beans.factory.BeanCurrentlyInCreationException:Errorcreatingbeanwithname'a':Requestedbeaniscurrentlyincreation:Isthereanunresolvablecircularreference?atorg.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)atorg.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)atorg.springframework.beans.factory。support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354)atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)atorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)atorg.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)atorg.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)atorg.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)atorg.springframework.beans.factory.support.AbstractBeanFactory.getBean(Abstract.javaBean:Factory)208)atorg.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)atorg.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)atorg.springframework.context.support.AbstractApplicationContext。刷新(AbstractApplicationContext.java:583)atorg.springframework.boot.SpringApplication.refresh(SpringApplication.java:782)atorg.springframework.boot.SpringApplication.refresh(SpringApplication.java:774)atorg.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)atorg.springframework.boot.SpringApplication.run(SpringApplication.java:339)atorg.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123)atorg.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoadermeworkDelegate.java:99)测试上下文。cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)...68moreCausedby:org.springframework.beans.factory.UnsatisfiedDependencyException:Errorcreatingbeanwithname'b'defined\TdbestData\Tdbtarget\test-classes\com\db\model\B。类]:通过构造函数参数0表达的不满意依赖关系;嵌套异常是org.springframework.beans.factory.BeanCurrentlyInCreationException:创建名称为“a”的bean时出错:请求的bean当前正在通过IsthereanunTMresolvercircuence创建吗?难道spring对这种循环依赖真的束手无策?其实不然,spring也有大杀器@Lazy...只是让我们对刚才的两个类做一个小小的修改:为什么lazy可以解决这个问题呢?逆向@Lazy注解,从源码可以看出,我们其实是为@Lazy的依赖返回了一个代理类(以下简称LazyProxy),而不是通过getBean获取目标bean注入,实际获取bean逻辑,它被封装到一个TargetSource类的getTarget方法中,而这个TargetSource类最终是用来生成LazyProxy的,那么我们是不是可以推测LazyProxy应该持有这个TargetSource对象。从我们懒加载的语义来看,就是在实际使用bean的时候(调用bean的某个方法时)注入/初始化属性。所以对于当前的例子来说,就是说在创建B的时候,并没有调用getBean("a")来获取构造函数的参数,而是直接生成了一个LazyProxy作为B构造函数的参数,而B之后,当真正调用A的方法,会调用TargetSource中的getTarget获取A实例,即会调用getBean("a")。这个时候A已经实例化了,所以不会有循环依赖的问题了。
