是高级这样的,有个实习生朋友问了我循环依赖的被构问题,我将Spring内部的造器三级缓存原理都跟他说了,并保证Spring已经解决了这个问题,循环然后他扔了一道题给我,依赖说报错了。难住
好家伙,高级感情是被构想我让我查bug
你们看看?
@Component public class A { private final B b; public A(final B b) { this.b = b; } public void print() { System.out.println("in a"); } } @Component public class B { private final A a; public B(final A a) { this.a = a; } public void print() { System.out.println("in b"); } } Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name a defined in file [C:\soft\code\common\MongodbDataTest\dbDataTest\target\test-classes\com\db\model\A.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name b defined in file [C:\soft\code\common\MongodbDataTest\dbDataTest\target\test-classes\com\db\model\B.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name a: Requested bean is currently in creation: Is there an unresolvable circular reference? at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) ... 68 more Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name b defined in file [C:\soft\code\common\MongodbDataTest\dbDataTest\target\test-classes\com\db\model\B.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name a: Requested bean is currently in creation: Is there an unresolvable circular reference?这TM,原来Spring并没有解决构造器循环依赖
难道,造器spring对于这种循环依赖真的循环束手无策了么?
其实不是的,spring还有@Lazy这个大杀器...只需要我们对刚刚那两个类小小的依赖改造一下:
lazy为啥可以解决这个问题?
反调@Lazy注解可以看到
从源码我们可以看到,云南idc服务商对于@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早就实例化好了,所以也就不会有循环依赖问题了。服务器租用