现在,就走到了我们自定义的getObject方法,由于我们调用了context.getBean("normalBeanB", NormalBeanB.class),此时,将会去创建B对象,在创建过程中,先将B的早期对象放入三级缓存,紧接着填充属性,发现依赖了A对象,又要倒回来创建A对象,从而又回到上面的逻辑,再次调用我们自定义的getObject方法,这个时候会发生什么呢?
又要去创建B对象...(Spring:心好累)
但是!此时我们在创建B时,是直接通过getBean在缓存中获取到了B的早期对象,得以返回了!于是我们自定义的getObject调用成功,返回了一个完整的A对象!
但是此时FactoryBean的缓冲中还是什么都没有的。
// 又从缓存中取了一次 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; }这一次取alreadyThere必然是null,流程继续执行,将此时将获取到的bean放入缓存
this.factoryBeanObjectCache.put(beanName, object);从FactoryBean获取对象的流程结束,返回到创建B的过程中,B对象此时的属性也得以填充,再返回到第一次创建A的过程,也就是我们第一次调用自定义的getObject方法,调用完毕,返回到这里
// 获取bean,调用factoryBean的getObject() object = doGetObjectFromFactoryBean(factory, beanName); Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere;那么,此时this.factoryBeanObjectCache.get(beanName)能从缓冲中拿到对象了吗?有没有发现,拿到了刚刚B对象填充属性时再次创建A对象放进去的!
所以,明白这里为什么要再次从缓存中获取了吧?就是为了解决由于循环依赖时调用了两次自定义的getObject方法,从而创建了两个不相同的A对象,保证我们返回出去的A对象唯一!
怕小伙伴晕了,画个图给大家
5. 工厂Bean与工厂Bean之间我们已经举例4种循环依赖的栗子,Spring都有所解决,那么有没有Spring也无法解决的循环依赖问题呢?
有的!就是这个FactoryBean与FactoryBean的循环依赖!
假设工厂对象A依赖工厂对象B,工厂对象B依赖工厂对象A,那么,这次的栗子会是什么样呢?
普通对象
public class NormalBeanA { private NormalBeanB normalBeanB; public void setNormalBeanB(NormalBeanB normalBeanB) { this.normalBeanB = normalBeanB; } } public class NormalBeanB { private NormalBeanA normalBeanA; public void setNormalBeanA(NormalBeanA normalBeanA) { this.normalBeanA = normalBeanA; } }工厂对象
@Component public class FactoryBeanA implements FactoryBean<NormalBeanA> { @Autowired private ApplicationContext context; @Override public NormalBeanA getObject() throws Exception { NormalBeanA normalBeanA = new NormalBeanA(); NormalBeanB normalBeanB = context.getBean("factoryBeanB", NormalBeanB.class); normalBeanA.setNormalBeanB(normalBeanB); return normalBeanA; } @Override public Class<?> getObjectType() { return NormalBeanA.class; } } @Component public class FactoryBeanB implements FactoryBean<NormalBeanB> { @Autowired private ApplicationContext context; @Override public NormalBeanB getObject() throws Exception { NormalBeanB normalBeanB = new NormalBeanB(); NormalBeanA normalBeanA = context.getBean("factoryBeanA", NormalBeanA.class); normalBeanB.setNormalBeanA(normalBeanA); return normalBeanB; } @Override public Class<?> getObjectType() { return NormalBeanB.class; } }首先,我们开始创建对象A,此时为调用工厂对象A的getObject方法,转而去获取对象B,便会走到工厂对象B的getObject方法,然后又去获取对象A,又将调用工厂对象A的getObject,再次去获取对象B,于是再次走到工厂对象B的getObject方法......此时,已经历了一轮循环,却没有跳出循环的迹象,妥妥的死循环了。
我们画个图吧~