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

358 阅读6分钟

写在前面的话

废话不多说

这是接系列文章3里面提到ObjectFactory的核心部分其实只是调用了createBean方法,

还需要深入createBean方法才能得出最终的结果。

本片我们就进入createBean方法,用源码层面看准备创建bean时都做了什么

createBean方法 准备创建bean

我们先看createBean方法的源码。

/**
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * 这个类的中心方法:创建bean实例,
 *  填充bean实例,应用后处理器等。
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 锁定class,根据设置的class属性或者根据className来解析class
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // 验证及准备覆盖的方法
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 给BeanPostProcessors一个机会来返回来替代真正的实例
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // 进行bean的创建
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isDebugEnabled()) {
         logger.debug("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

可以看出这也并不是真正的创建,而只是做了一些准备工作。真实的创建是在doCreateBean方法中。

但是不妨碍我们先来看看CreateBean做了些什么。

  1. 根据设置的class属性或者根据className来解析class。
  2. 对override属性进行标记及验证。
  3. 应用初始化前的后处理器,解析指定bean是否存在初始化钱的短路操作。
  4. 创建bean。

我们下面针对上面的2和3点再做一下具体的说明。

override属性进行标记及验证

源码在AbstractBeanDefinition的prepareMethodOverrides方法中,如下:

/**
 * Validate and prepare the method overrides defined for this bean.
 * Checks for existence of a method with the specified name.
 * 验证并准备为该bean定义的方法重写。
 * 检查指定名称的方法是否存在。
 * @throws BeanDefinitionValidationException in case of validation failure
 */
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   // Check that lookup methods exist and determine their overloaded status.
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}

/**
 * Validate and prepare the given method override.
 * Checks for existence of a method with the specified name,
 * marking it as not overloaded if none found.
 * 验证并准备给定的方法重写。  
 * 检查指定名称的方法是否存在,  
 * 如果没有找到,则标记为未重载。  
 * @param mo the MethodOverride object to validate
 * @throws BeanDefinitionValidationException in case of validation failure
 */
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
   // 获取对应类中对应方法名的个数
   int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
   if (count == 0) {
      throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
   }
   else if (count == 1) {
      // Mark override as not overloaded, to avoid the overhead of arg type checking.
      // 标记MethodOverride暂未被覆盖,避免参数类型检查的开销。
      mo.setOverloaded(false);
   }
}

prepareMethodOverrides方法的作用

在继续解读之前,我们需要知道prepareMethodOverrides方法的作用。

要知道在Spring的配置中没有类似override-method的配置,这个方法的作用是什么呢?

其实在Spring中虽然确实没有override-method的配置,但是Spring却配置了lookup-method

replace-method的配置,而这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里,而prepareMethodOverrides方法的操作也是针对这两个配置的。

接着看回AbstractBeanDefinition的两个函数,lookup-method和replace-method的实现原理其实是在

bean实例化的时候如果检测到存在methodOverrides属性,就会动态地为当前bean生成代理并使用对应的拦截器为bean做增强处理。

resolveBeforeInstantiation 实例化的前置处理

resolveBeforeInstantiation(beanName, mbdToUse)对BeanDefinition中的属性做些前置处理。

还有个重要的点是,在函数中提供了一个短路判断。

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 给BeanPostProcessors一个机会来返回来替代真正的实例
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
   return bean;
}

当经过前置处理后返回的结果如果不为空,那么会直接略过后续的bean的创建而直接返回结果

这一特性容易被忽略,但是作用巨大,我们熟知的AOP功能就是基于这里的判断的。

resolveBeforeInstantiation源码如下:

/**
 * Apply before-instantiation post-processors, resolving whether there is a
 * before-instantiation shortcut for the specified bean.
 * 应用实例化前的后处理器,解析是否存在
 * 为指定的bean实例化前的快捷方式。
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @return the shortcut-determined bean instance, or {@code null} if none
 */
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   // 如果尚未被解析
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

下面接着对applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization两个方法进行讲解。

这两个方法实现就是对后处理器中的所有InstantiationAwareBeanPostProcessor类型的后处理器进行postProcessBeforeInstantiation方法和BeanPostProcessor的postProcessAfterInitialization方法进行调用。

1.applyBeanPostProcessorsBeforeInstantiation 实例化前的后处理器应用

/**
 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
 * 将InstantiationAwareBeanPostProcessors应用到指定的bean定义中  
 * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
 * <p>Any returned object will be used as the bean instead of actually instantiating
 * the target bean. A {@code null} return value from the post-processor will
 * result in the target bean being instantiated.
 * @param beanClass the class of the bean to be instantiated
 * @param beanName the name of the bean
 * @return the bean object to use instead of a default instance of the target bean, or {@code null}
 * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
 */
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
         if (result != null) {
            return result;
         }
      }
   }
   return null;
}

bean的实例化前调用,是将AbstractBeanDefinition转换为BeanWrapper前的处理。

给子类一个修改BeanDefinition的机会,当程序经过这个方法后,bean可能就不是我们认为的bean了,

而是可能成为一个经过处理的代理bean,可能是通过cglib生产,也可能是通过其他技术生产(JDK)。

重点关注:在bean的实例化钱会调用后处理器的方法进行处理

2.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;
}

在之前讲解从缓存中获取单例bean的时候就说过, Spring中的规则是在bean的初始化后尽可能的保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,

因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,

所以只能在这里应用后处理器的postProcessAfterInitialization方法。

写在后面的话

在本篇中我们已经知道了准备创建bean的时候Spring做了些什么,也知道具体的创建bean是在doCreateBean方法中,

所以在下一篇中我们会深入到创建bean的doCreateBean方法中讲解到底是怎么创建的。