Spring源码阅读之registerBeanPostProcessors()源码分析

上篇文章我们分析了invokeBeanFactoryPostProcessors()方法的实现,主要是BeanFactoryBeanDefinition定义在实例化之前做一些前置操作。接下来本文来看看registerBeanPostProcessors()的实现,上篇文章留了一个疑问,大家是否还记得?我们在本篇文章揭晓答案,本篇先来解读源码,后面附上测试用例。

  1. 回到AbstractApplicationContext.refresh()方法的registerBeanPostProcessors()地方,我们来看看实现,从方法中可以看出,调用了PostProcessorRegistrationDelegate类的静态方法。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

  1. PostProcessorRegistrationDelegate.registerBeanPostProcessors方法用于注册所有BeanPostProcessor实例(该方法比较长,但是流程很清晰,耐心开完)。看源码前首先需要明白两个类:

  • BeanPostProcessor: 一切BeanPostProcessor实例都需要直接或间接该接口。

  • MergedBeanDefinitionPostProcessor: 是一个接口,实现了BeanPostProcessor接口,并给出了一个方法。所以实现了该接口的类比实现了BeanPostProcessor类的优先级更高,功能更丰富。

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
      // Step1:获取所有直接或间接实现了BeanPostProcessor接口的BeanDefinition对应的processor名字。内部实现见源码分析3
      String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

      // Register BeanPostProcessorChecker that logs an info message when
      // a bean is created during BeanPostProcessor instantiation, i.e. when
      // a bean is not eligible for getting processed by all BeanPostProcessors.
      int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
      // Step2:添加一个BeanPostProcessor检查器,该检查器的作用:是在创建BeanPostProcessor时记录日志、创建BeanPostProcessor发生异常时记录日志等等操作。
      beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

      // Separate between BeanPostProcessors that implement PriorityOrdered,
      // Ordered, and the rest.
      // Step3:存放实现了PriorityOrdered接口的BeanPostProcessor,其优先级最高。
      // PriorityOrdered接口作用:用于对BeanPostProcessor进行优先级排序的。和上一篇关于BeanFactoryPostProcessor的排序功能一样。
      List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
      // Step4:存放内部实现的BeanPostProcessor。
      List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
      // Step5:存放实现了Ordered接口的BeanPostProcessor,其优先级低于PriorityOrdered接口
      // Ordered接口作用:也是排序功能。
      List<String> orderedPostProcessorNames = new ArrayList<>();
      // Step6:存放除去内部的和有优先级的BeanPostProcessor后,剩余的BeanPostProcessor
      List<String> nonOrderedPostProcessorNames = new ArrayList<>();
      // Step7:遍历BeanPostProcessor对应的名字,进行分堆和创建Bean实例操作。关于创建Bean实例在后面创建Bean实例专门介绍,这里不展开。
      for (String ppName : postProcessorNames) {
          if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
              BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
              priorityOrderedPostProcessors.add(pp);
              if (pp instanceof MergedBeanDefinitionPostProcessor) {
                  internalPostProcessors.add(pp);
              }
          }
          else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
              orderedPostProcessorNames.add(ppName);
          }
          else {
              nonOrderedPostProcessorNames.add(ppName);
          }
      }

      // First, register the BeanPostProcessors that implement PriorityOrdered.
      // Step8:对PriorityOrdered相关的BeanPostProcessor进行排序操作,排序的依据是重写了PriorityOrdered的getOrder的返回值
      sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
      // Step9:将排序后的BeanPostProcessor一次注册到BeanFactory里面。
      registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

      // Next, register the BeanPostProcessors that implement Ordered.
      // Step10:遍历实现了Ordered接口的BeanPostProcessor,如果改processor实现了MergedBeanDefinitionPostProcessor接口,将其加入到内部的BeanPostProcessor集合里面。
      List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
      for (String ppName : orderedPostProcessorNames) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          orderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
              internalPostProcessors.add(pp);
          }
      }
      // Step11:排序
      sortPostProcessors(orderedPostProcessors, beanFactory);
      // Step12:注册
      registerBeanPostProcessors(beanFactory, orderedPostProcessors);

      // Now, register all regular BeanPostProcessors.
      // Step13:对无优先级的BeanPostProcessor进行遍历,将实现了MergedBeanDefinitionPostProcessor接口的加入到内部BeanPostProcessor的集合中
      List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
      for (String ppName : nonOrderedPostProcessorNames) {
          BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
          nonOrderedPostProcessors.add(pp);
          if (pp instanceof MergedBeanDefinitionPostProcessor) {
              internalPostProcessors.add(pp);
          }
      }
      // Step14:没有先后顺序,一次注册这些Bean实例到BeanFactory里面。
      registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

      // Finally, re-register all internal BeanPostProcessors.
      // Step15:最后对所有的内部BeanPostProcessor实例进行排序操作,并将其注册到BeanFactory里面。
      sortPostProcessors(internalPostProcessors, beanFactory);
      registerBeanPostProcessors(beanFactory, internalPostProcessors);

      // Re-register post-processor for detecting inner beans as ApplicationListeners,
      // moving it to the end of the processor chain (for picking up proxies etc).
      // Step16:对BeanFactory添加一个一个全局的监听器
      beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

  1. 我们来看下BeanPostProcessor对应的beanName是怎么获取到的。

public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
      // Step1:当前BeanFactory是否冻结,冻结返回true(就是说当前BeanFactory的BeanDefinition定义是否不可以被修改)
      if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
          return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
      }
      // Step2:从当前BeanFactory的缓存里面获取对应的BeanPostProcessor名字。如果有直接返回(在Spring源码中大量用到了这种缓存机制来提升Spring容器初始化的速度)
      Map<Class<?>, String[]> cache =
              (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
      String[] resolvedBeanNames = cache.get(type);
      if (resolvedBeanNames != null) {
          return resolvedBeanNames;
      }
      // Step3:都没有取到,则根据type去加载相应的名字
      resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
      if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
          cache.put(type, resolvedBeanNames);
      }
      return resolvedBeanNames;
}

  1. 来看看根据type如果获取到对应的BeanPostProcessor名字,这里稍微比较复杂一点,归纳一下其实就是遍历所有的beanName,然后拿type去匹配,如果能匹配的上就认为是目标的BeanPostProcessor对应的baneName

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
      List<String> result = new ArrayList<>();

      // Check all bean definitions.
      // Step1:遍历当前BeanFactory里面所有的beanNames
      for (String beanName : this.beanDefinitionNames) {
          // Only consider bean as eligible if the bean name
          // is not defined as alias for some other bean.
          // Setp1.1:判断当前beanName是否是别名,所以if里面的逻辑是针对非别名的beanName处理。
          if (!isAlias(beanName)) {
              try {
                  // Step1.1.1:根据beanName获取对应的BeanDefinition定义,具体逻辑之前介绍过,在这里就不展开了。
                  RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                  // Only check bean definition if it is complete.
                  // Step1.1.2:检查BeanDefinition定义是否完整。即当前BeanDefinition定义是:非抽象的 && (提前加载 || (有对应的BeanClass || 非懒加载 || 允许提前加载bean)&& 是否提前初始化指定类型的bean)
                  // 总结大概意思就是当前BeanDefinition定义是非抽象的且可以提前加载
                  if (!mbd.isAbstract() && (allowEagerInit ||
                          (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                  !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                      // In case of FactoryBean, match object created by FactoryBean.
                      // Setp1.1.2.1:根据beanName和对应的BeanDefinition定义判断是否是一个FactoryBean。
                      boolean isFactoryBean = isFactoryBean(beanName, mbd);
                      // Step1.1.2.2:返回此BeanDefinition被修饰的BeanDefinitionHolder对象。
                      BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                      // Step1.1.2.3:判断beanName和对应的BeanDefinition是否匹配
                      boolean matchFound =
                              (allowEagerInit || !isFactoryBean ||
                                      (dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
                              (includeNonSingletons ||
                                      (dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
                              isTypeMatch(beanName, type);
                      // Step1.1.2.4:没匹配到 %% 是BeanFactory,则添加BeanFactory的前缀,在匹配一次。
                      if (!matchFound && isFactoryBean) {
                          // In case of FactoryBean, try to match FactoryBean instance itself next.
                          beanName = FACTORY_BEAN_PREFIX + beanName;
                          matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
                      }
                      // Step1.1.2.5:匹配到则将beanName加到结果集中
                      if (matchFound) {
                          result.add(beanName);
                      }
                  }
              }
              catch (CannotLoadBeanClassException ex) {
                  if (allowEagerInit) {
                      throw ex;
                  }
                  // Probably contains a placeholder: let's ignore it for type matching purposes.
                  if (this.logger.isDebugEnabled()) {
                      this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
                  }
                  onSuppressedException(ex);
              }
              catch (BeanDefinitionStoreException ex) {
                  if (allowEagerInit) {
                      throw ex;
                  }
                  // Probably contains a placeholder: let's ignore it for type matching purposes.
                  if (this.logger.isDebugEnabled()) {
                      this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
                  }
                  onSuppressedException(ex);
              }
          }
      }

      // Check manually registered singletons too.
      // Step2:检查手动注册的单例Bean
      for (String beanName : this.manualSingletonNames) {
          try {
              // In case of FactoryBean, match object created by FactoryBean.
              // Step2.1:是一个FactoryBean并且匹配到了,则加入到结果集中
              if (isFactoryBean(beanName)) {
                  if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
                      result.add(beanName);
                      // Match found for this bean: do not match FactoryBean itself anymore.
                      continue;
                  }
                  // In case of FactoryBean, try to match FactoryBean itself next.
                  beanName = FACTORY_BEAN_PREFIX + beanName;
              }
              // Match raw bean instance (might be raw FactoryBean).
              // Step2.2:非FactoryBean并且匹配到了,则加入到结果集中
              if (isTypeMatch(beanName, type)) {
                  result.add(beanName);
              }
          }
          catch (NoSuchBeanDefinitionException ex) {
              // Shouldn't happen - probably a result of circular reference resolution...
              if (logger.isDebugEnabled()) {
                  logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
              }
          }
      }
      // Step3:返回匹配到的结果集
      return StringUtils.toStringArray(result);
}

5. 以上即为源码的分析,所以的工作就是将BeanPostProcessor注册到BeanFactory里面,然后在 bean 实例初始化前做一些工作(关于这个我们在介绍 bean 实例初始化的地方会介绍)。接下来,来看一个例子来理解一下整个过程。

// 使用方法比较简单,我们创建一个MyBeanPostProcessor,其实现了BeanPostProcessor接口和Ordered的接口
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

/**
 * @author zxz
 * 自定义BeanPostProcessor
 */
public class MyBeanPostProcessor implements BeanPostProcessor, Ordered {
    public int getOrder() {
        // 这个返回值是用来对实现了Ordered接口的BeanPostProcessor进行排序的
        return 0;
    }

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization,该方法是在Bean实例初始化前被调用,执行一些特殊的逻辑");
        // 这里写自己要做的特殊逻辑
        if (bean instanceof UserService) {
            System.out.println("UserService instance bean before");
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor.postProcessAfterInitialization,该方法实在Bean实例初始化后被调用,执行特殊的逻辑");
        // 这里写自己要做的特殊逻辑
        if (bean instanceof UserService) {
            System.out.println("UserService instance bean after");
        }
        return bean;
    }
}
// xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="UserServiceImpl"/>
    <!-- 注入自定义的BeanPostProcessor -->
    <bean id="myBeanPostProcessor" class="MyBeanPostProcessor"/>
</beans>
// 单测
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JuniteTest {

    @Test
    public void testBeanPostProcessor() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = context.getBean(UserService.class);
        userService.save();
    }
}

从输出结果来看,首先调用了重写的postProcessBeforeInitialization()postProcessAfterInitialization()方法。然后在UserServicesave方法。


6. 以上内容为BeanPostProcessor注册的全流程。现在来回答一下上篇文章留下的问题,invokeBeanFactoryPostProcessors()registerBeanPostProcessors()区别?

  • invokeBeanFactoryPostProcessors():操作的对象是BeanDefinition定义,在此阶段我们随意修改BeanDefinition定义的属性相关。BeanFactoryPostProcessor只提供了一个方法:postProcessBeanFactory()

  • registerBeanPostProcessors():操作的对象是BeanDefinition定义对应的 Bean 实例,BeanPostProcessor提供了两个方法:postProcessBeforeInitialization()postProcessAfterInitialization()


总结

registerBeanPostProcessors方法主要功能是将所有实现了BeanPostProcessor接口或者实现了MergedBeanDefinitionPostProcessor接口的类对应的实例注册到BeanFactory中(注意是将 Bean 实例注册到BeanFactory里面)。

在该方法内部将BeanPostProcessor分为四类,分别是实现了PriorityOrdered接口的、实现了Ordered接口的、内部的和普通的。按照优先级依次排序将这四类BeanPostProcessor注册到BeanFactory里面。

BeanPostProcessor提供的两个方法的调用时机是在 Bean 实例初始化前后的时候被调用。

下一篇我们就来介绍 Spring 最核心的一个方法:finishBeanFactoryInitialization(),看看它是怎么把BeanDefinition定义转化成对应的 Bean 实例的,敬请期待。


欢迎关注我,共同学习

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值