Spring源码分析之循环依赖及解决方案 (3)

不知道小伙伴发现没有,earlyProxyReferences这个缓存可不就是我们在填充B的属性,进而从缓存中获取A时放进去的吗?不信您往上翻到getEarlyBeanReference的步骤看看~

所以,此时并未进行任何处理,依旧返回了我们的原对象A,看来这里并没有我们要的答案,那就继续吧~

// 是否允许暴露早期对象 if (earlySingletonExposure) { // 从缓存池中获取早期对象 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { // bean为初始化前的对象,exposedObject为初始化后的对象 // 判断两对象是否相等,基于上面的分析,这两者是相等的 if (exposedObject == bean) { // 将早期对象赋给exposedObject exposedObject = earlySingletonReference; } } }

我们来分析一下上面的逻辑,getSingleton从缓存池中获取早期对象返回的是什么呢?

synchronized (this.singletonObjects) { // 从早期对象缓存池中获取,此时就拿到了我们填充B属性时放入的A的代理对象 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 从三级缓存中获取回调函数 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 调用回调方法获取早期bean singletonObject = singletonFactory.getObject(); // 将早期对象放到二级缓存,移除三级缓存 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } }

发现了吗?此时我们就获取到了A的代理对象,然后我们又把这个对象赋给了exposedObject,此时创建对象的流程走完,我们得到的A不就是个代理对象了吗~

此次栗子是先创建需要代理的对象A,假设我们先创建普通对象B会发生什么呢?

3. 代理对象与代理对象

代理对象与代理对象的循环依赖是怎么样的呢?解决过程又是如何呢?这里就留给小伙伴自己思考了,其实和普通Bean与代理对象是一模一样的,小伙伴想想是不是呢,这里我就不做分析了。

4. 普通Bean与工厂Bean

这里所说的普通Bean与工厂Bean并非指bean与FactoryBean,这将毫无意义,而是指普通Bean与FactoryBean的getObject方法产生了循环依赖,因为FactoryBean最终产生的对象是由getObject方法所产出。我们先来看看栗子吧~

假设工厂对象A依赖普通对象B,普通对象B依赖普通对象A。

小伙伴看到这里就可能问了,诶~你这不对呀,怎么成了「普通对象B依赖普通对象A」呢?不应该是工厂对象A吗?是这样的,在Spring中,由于普通对象A是由工厂对象A产生,所有在普通对象B想要获取普通对象A时,其实最终寻找调用的是工厂对象A的getObject方法,所以只要普通对象B依赖普通对象A就可以了,Spring会自动帮我们把普通对象B和工厂对象A联系在一起。

小伙伴,哦~

普通对象A

public class NormalBeanA { private NormalBeanB normalBeanB; public void setNormalBeanB(NormalBeanB normalBeanB) { this.normalBeanB = normalBeanB; } }

工厂对象A

@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("normalBeanB", NormalBeanB.class); normalBeanA.setNormalBeanB(normalBeanB); return normalBeanA; } @Override public Class<?> getObjectType() { return NormalBeanA.class; } }

普通对象B

@Component public class NormalBeanB { @Autowired private NormalBeanA normalBeanA; }

假设我们先创建对象A

由于FactoryBean和Bean的创建过程是一样的,只是多了步getObject,所以我们直接定位到调用getObject入口

if (mbd.isSingleton()) { // 开始创建bean sharedInstance = getSingleton(beanName, () -> { // 创建bean return createBean(beanName, mbd, args); }); // 处理FactoryBean bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 先尝试从缓存中获取,保证多次从工厂bean获取的bean是同一个bean object = getCachedObjectForFactoryBean(beanName); if (object == null) { // 从FactoryBean获取对象 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } } protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { // 加锁,防止多线程时重复创建bean synchronized (getSingletonMutex()) { // 这里是Double Check Object object = this.factoryBeanObjectCache.get(beanName); if (object == null) { // 获取bean,调用factoryBean的getObject() object = doGetObjectFromFactoryBean(factory, beanName); } // 又从缓存中取了一次,why? 我们慢慢分析 Object alreadyThere = this.factoryBeanObjectCache.get(beanName); if (alreadyThere != null) { object = alreadyThere; }else{ // ...省略初始化bean的逻辑... // 将获取到的bean放入缓存 this.factoryBeanObjectCache.put(beanName, object); } } } private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName){ return factory.getObject(); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjfgf.html