高级开发竟然被构造器循环依赖难住了?

是高级这样的,有个实习生朋友问了我循环依赖的被构问题,我将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注解可以看到

从源码我们可以看到,源码库对于@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早就实例化好了,所以也就不会有循环依赖问题了。亿华云

IT科技
上一篇:2016年1月1日:注册价格将降至每年7欧元。
下一篇:.net 适用于从事Internet相关的网络服务的机构或公司