从源码层面解读spring中bean的循环依赖解决方案(4)

写在前面的话

源码层面解读spring中bean的循环依赖解决方案系列来到了最终章,

我们主要研究spring如何从bean的实例中获取对象

从bean的实例中获取对象

在getBean的方法中,getObjectForBeanInstance是一个高频使用的方法,无论是从缓存中获取还是从不同的scope策略加载bean。

这个方法的主要作用就是检测当前bean是否是FactoryBean类型的bean,如果是,就需要条
用该bean队友的FactoryBean实例中的getObject()作为放回值。

这里抛出一个问题,我们从从缓存中获取还是从不同的scope策略加载获取到的bean,都只是原始的bean状态,

不一定是我们想要的bean。

比如,我们需要对工厂bean进行处理的时候,上面获取到的bean就只是初始状态,而我们其实需要的是工厂bean中定义的factory-method方法返回的bean,getObjectForBeanInstance方法就能完成这个工作。

getObjectForBeanInstance

/**
 * Get the object for the given bean instance, either the bean
 * instance itself or its created object in case of a FactoryBean.
 * 获取给定bean实例的对象,对于FactoryBean,可以是bean实例本身,也可以是它创建的对象。
 * @param beanInstance the shared bean instance
 * @param name the name that may include factory dereference prefix
 * @param beanName the canonical bean name
 * @param mbd the merged bean definition
 * @return the object to expose for the bean
 */
protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

   // Don't let calling code try to dereference the factory if the bean isn't a factory.
   // 如果指定的name是工程相关(以&为前缀)且beanInstance又不是FactoryBean类型则严重不通过
   if (BeanFactoryUtils.isFactoryDereference(name)) {
      if (beanInstance instanceof NullBean) {
         return beanInstance;
      }
      if (!(beanInstance instanceof FactoryBean)) {
         throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
      }
   }

   // Now we have the bean instance, which may be a normal bean or a FactoryBean.
   // If it's a FactoryBean, we use it to create a bean instance, unless the
   // caller actually wants a reference to the factory.
   // 现在我们有了bean实例,它可以是一个普通的bean或FactoryBean。  
   // 如果它是一个FactoryBean,我们使用它来创建一个bean实例,除非  
   // 调用者实际上想要一个对工厂的引用,而不是工程的getObject方法队友的实例那么传入的neam应该加前缀&
   if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
   }
   //加载FactoryBean
   Object object = null;
   if (mbd == null) {
      //尝试从缓存中加载bean
      object = getCachedObjectForFactoryBean(beanName);
   }
   if (object == null) {
      // Return bean instance from factory.
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      // Caches object obtained from FactoryBean if it is a singleton.
      if (mbd == null && containsBeanDefinition(beanName)) {
         mbd = getMergedLocalBeanDefinition(beanName);
      }
      //是否是用户定义的而不是应用程序本身定义的
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
   }
   return object;
}

getObjectForBeanInstance内部做了一下几件事:

1.对FactoryBean正确性进行验证。

2.非FactoryBean不做任何处理。

3.对bean进行转换

4.把从Factory解析bean的工作委托给getObjectFromFactoryBean方法

getObjectFromFactoryBean

/**
 * Obtain an object to expose from the given FactoryBean.
 * 获取要从给定的FactoryBean公开的对象。
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @param shouldPostProcess whether the bean is subject to post-processing
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
   //如果是单例模式
   if (factory.isSingleton() && containsSingleton(beanName)) {
      synchronized (getSingletonMutex()) {
         Object object = this.factoryBeanObjectCache.get(beanName);
         if (object == null) {
            // 获取对象从FactoryBean
            object = doGetObjectFromFactoryBean(factory, beanName);
            // Only post-process and store if not put there already during getObject() call above
            // (e.g. because of circular reference processing triggered by custom getBean calls)
            // 如果在上面调用getObject()时没有放在那里,则只进行后处理和存储
            // (例如,由于循环引用处理由自定义getBean调用触发)
            Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
            if (alreadyThere != null) {
               object = alreadyThere;
            }
            else {
               if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     // Temporarily return non-post-processed object, not storing it yet..
                     // 暂时返回非后期处理的对象,不存储它。
                     return object;
                  }
                  beforeSingletonCreation(beanName);
                  try {
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     afterSingletonCreation(beanName);
                  }
               }
               if (containsSingleton(beanName)) {
                  this.factoryBeanObjectCache.put(beanName, object);
               }
            }
         }
         return object;
      }
   }
   else {
      // 获取对象从FactoryBean
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (shouldPostProcess) {
         try {
            object = postProcessObjectFromFactoryBean(object, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
         }
      }
      return object;
   }
}

getObjectFromFactoryBean方法中只做了一件事情就是返回的bean如果是单例,
那就必须要保证全局唯一。

同时,也是因为是单例,索引不需要重复创建,可以使用缓存来提高性能,也就是说已经加载过就要记录下来以便下次服用,否则的话就直接获取了。

doGetObjectFromFactoryBean

在这个方法中就有了直接调用的getObject()方法。

object = factory.getObject();

/**
 * Obtain an object to expose from the given FactoryBean.
 * 获取要从给定的FactoryBean公开的对象。
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
   Object object;
   try {
      //需要权限验证
      if (System.getSecurityManager() != null) {
         AccessControlContext acc = getAccessControlContext();
         try {
            object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         //直接调用getObject方法
         object = factory.getObject();
      }
   }
   catch (FactoryBeanNotInitializedException ex) {
      throw new BeanCurrentlyInCreationException(beanName, ex.toString());
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
   }

   // Do not accept a null value for a FactoryBean that's not fully
   // initialized yet: Many FactoryBeans just return null then.
   //不接受一个不完全的FactoryBean的空值  
   //许多FactoryBeans返回null  
   if (object == null) {
      if (isSingletonCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(
               beanName, "FactoryBean which is currently in creation returned null from getObject");
      }
      object = new NullBean();
   }
   return object;
}

至此我们讲述了整个从FactoryBean的调用方法, 就是如果bean声明为FactoryBean类型,则当提取bean时提取的并不是FactoryBean,而是FactoryBean中对应的getObject方法返回的bean,

方法实现就是doGetObjectFromFactoryBean。

接下来回到getObjectFromFactoryBean方法中,

有这样一段代码:

            if (shouldPostProcess) {
                  if (isSingletonCurrentlyInCreation(beanName)) {
                     // Temporarily return non-post-processed object, not storing it yet..
                     // 暂时返回非后期处理的对象,不存储它。
                     return object;
                  }
                  beforeSingletonCreation(beanName);
                  try {
                      //调用ObjectFactory的后处理器
                     object = postProcessObjectFromFactoryBean(object, beanName);
                  }
                  catch (Throwable ex) {
                     throw new BeanCreationException(beanName,
                           "Post-processing of FactoryBean's singleton object failed", ex);
                  }
                  finally {
                     afterSingletonCreation(beanName);
                  }
               }

里面提到postProcessObjectFromFactoryBean方法,在

            //获取对象从FactoryBean
            object = doGetObjectFromFactoryBean(factory, beanName);

得到我们想要的结果后,并没有直接返回,而是调用了后处理器操作postProcessObjectFromFactoryBean。

postProcessObjectFromFactoryBean

/**
 * Post-process the given object that has been obtained from the FactoryBean.
 * The resulting object will get exposed for bean references.
 * <p>The default implementation simply returns the given object as-is.
 * Subclasses may override this, for example, to apply post-processors.
 * 对从FactoryBean获得的给定对象进行后处理。
 * 结果对象将被公开给bean引用。
 * <p>默认的实现简单地返回给定的对象。
 * 子类可以覆盖这个,例如,应用后处理器。
 * @param object the object obtained from the FactoryBean.
 * @param beanName the name of the bean
 * @return the object to expose
 * @throws org.springframework.beans.BeansException if any post-processing failed
 */
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
   return object;
}

这里提到postProcessObjectFromFactoryBean方法是留给子类覆盖的。

所以我们接着看子类AbstractAutowireCapableBeanFactory对postProcessObjectFromFactoryBean方法的覆写源码。

/**
 * Applies the {@code postProcessAfterInitialization} callback of all
 * registered BeanPostProcessors, giving them a chance to post-process the
 * object obtained from FactoryBeans (for example, to auto-proxy them).
 * 应用所有的{@code postProcessAfterInitialization}回调  
 * 注册了BeanPostProcessors,让他们有机会对  
 * 从FactoryBeans获取的对象(例如,自动代理它们)。  
 * @see #applyBeanPostProcessorsAfterInitialization
 */
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
   return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

接着看applyBeanPostProcessorsAfterInitialization方法

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}

可以看出就是会调用postProcessAfterInitialization方法,

Spring获取bean的一条规则:
尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理。

这个postProcessAfterInitialization方法在
从源码层面解读spring中bean的循环依赖解决方案(3)
中的初始化bean中就有过介绍,目的是使用户可以根据自己的业务需求进行响应处理

写在后面的话

这一篇我们介绍了如何从bean的实例中获取对象,也从源码出发解释了如何从bean中获取对象。

下一篇我们回归正题,进入到createBean方法中去找寻创建bean的最终真相。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值