Spring的BeanFactoryPostProcessor接口示例代码详解

论坛 期权论坛 脚本     
niminba   2021-5-26 11:41   1036   0

接口简介

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

注意点:通过BeanDefinitionRegistryPostProcessor 注册的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法将得不到调用,具体的原因会在下面的代码中解释。

BeanFactoryPostProcessor 接口调用机制

BeanFactoryPostProcessor 接口的调用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

  // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
  // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
  if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
   beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
   beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }
 }

进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:

public static void invokeBeanFactoryPostProcessors(
   ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   // 用于存放已经处理过的Bean名字
  Set<String> processedBeans = new HashSet<>();
   // 一般会进入这个判断
  if (beanFactory instanceof BeanDefinitionRegistry) {
   BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    // 所谓的regularPostProcessors就是指实现BeanFactoryPostProcessor接口的Bean
   List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    // 所谓的registryProcessors就是指实现BeanDefinitionRegistryPostProcessor接口的Bean
   List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    // 这边遍历的是通过ApplicationContext接口注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口
    // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口区分开
   for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
     BeanDefinitionRegistryPostProcessor registryProcessor =
       (BeanDefinitionRegistryPostProcessor) postProcessor;
      //如果是BeanDefinitionRegistryPostProcessor,则先进行postProcessBeanDefinitionRegistry处理,这个方法一般进行BeanDefinition注册,从这边可以看出BeanDefinitionRegistryPostProcessor接口的方法先调用,所以优先级高于BeanFactoryPostProcessor
      // 通过这个代码可以看出,通过ApplicationContext直接注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor并不支持Order接口,而是根据注册的顺序执行
     registryProcessor.postProcessBeanDefinitionRegistry(registry);
      // 保存这个BeanDefinitionRegistryPostProcessor,因为还要执行这个类的BeanFactoryPostProcessor方法;
     registryProcessors.add(registryProcessor);
    }
    else {
      // 保存,后面还要执行这个类的BeanFactoryPostProcessor方法;
     regularPostProcessors.add(postProcessor);
    }
   }

   List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    // 这边获取的是BeanFactory中的BeanDefinitionRegistryPostProcessor
   String[] postProcessorNames =
     beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
   for (String ppName : postProcessorNames) {
     //先处理PriorityOrdered标注的BeanDefinitionRegistryPostProcessor
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      //将其标记为已经处理,防止重复处理
     processedBeans.add(ppName);
    }
   }
    // 将其排序,以便按顺序处理
   sortPostProcessors(currentRegistryProcessors, beanFactory);
    // 将其保存,以便处理这个类的BeanFactoryPostProcessor方法
   registryProcessors.addAll(currentRegistryProcessors);
    // 执行BeanDefinitionRegistryPostProcessor接口方法
   invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    // 清除,以便开始处理@Order标注的注解
   currentRegistryProcessors.clear();
  
    // 注意:这边重新获取BeanDefinitionRegistryPostProcessor是有深意的,因为上面在处理@PriorityOrdered标注的BeanDefinitionRegistryPostProcessor时可能又注入了新的BeanDefinitionRegistryPostProcessor。
   postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
   for (String ppName : postProcessorNames) {
     // 判断是否处理过,防止重复处理,下面的逻辑和上面相同, 不介绍了
    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     processedBeans.add(ppName);
    }
   }
   sortPostProcessors(currentRegistryProcessors, beanFactory);
   registryProcessors.addAll(currentRegistryProcessors);
   invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
   currentRegistryProcessors.clear();

    // 处理不标注注解的BeanDefinitionRegistryPostProcessor
   boolean reiterate = true;
   while (reiterate) {
    reiterate = false;
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
     if (!processedBeans.contains(ppName)) {
      currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      processedBeans.add(ppName);
      reiterate = true;
     }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    currentRegistryProcessors.clear();
   }

   // 调用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的优先级要高。
   invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  }

  else {
   // Invoke factory processors registered with the context instance.
   invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
  }

  // 开始处理BeanFactoryPostProcessor接口
  String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

  // 也是按照@PriorityOrdered @Ordered 和普通的方式进行处理
  List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
  List<String> orderedPostProcessorNames = new ArrayList<>();
  List<String> nonOrderedPostProcessorNames = new ArrayList<>();
  for (String ppName : postProcessorNames) {
    // 可能已经处理过
   if (processedBeans.contains(ppName)) {
    // skip - already processed in first phase above
   }
   else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
   }
   else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    orderedPostProcessorNames.add(ppName);
   }
   else {
    nonOrderedPostProcessorNames.add(ppName);
   }
  }
   // 先执行@PriorityOrdered标注的接口
  sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
  invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
   // 处理@Order标注的类
  List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
  for (String postProcessorName : orderedPostProcessorNames) {
    // 这边通过名字重新拿了Bean,应该是怕上面的处理改变了Bean
   orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  }
  sortPostProcessors(orderedPostProcessors, beanFactory);
  invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

  // 最后调用普通的BeanFactoryPostProcessor
  List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
  for (String postProcessorName : nonOrderedPostProcessorNames) {
   nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  }
  invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

  // Clear cached merged bean definitions since the post-processors might have
  // modified the original metadata, e.g. replacing placeholders in values...
  beanFactory.clearMetadataCache();
 }

简单总结

上面的方法看起来很长很复杂,但其实干的事情并不多,就调用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的实现。这边再简单总结下具体的过程:

step1:执行通过ApplicationContext#addBeanFactoryPostProcessor()方法注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

具体过程如下:假如通过ApplicationContext注册了一个BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么会先执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暂时都不会在这步执行。

另外需要注意的是:通过ApplicationContext注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered顺序处理,而是按照我们添加的顺序处理

step2:处理BeanFactory中的BeanDefinitionRegistryPostProcessor,处理的顺序是先处理@PriorityOrdered标注的,再处理@Ordered标注的,最后处理普通的BeanDefinitionRegistryPostProcessor。到这边,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已经调用完毕,下面就开始处理BeanFactoryPostProcessor的postProcessBeanFactory方法。

step3:调用BeanDefinitionRegistryPostProcessor实现的postProcessBeanFactory方法(因为BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)

step4:调用通过ApplicationContext#addBeanFactoryPostProcessor()注册的“单纯”的BeanFactoryPostProcessor

step5:调用BeanFactory中的BeanFactoryPostProcessor,调用顺序也是按照@PriorityOrdered和@Ordered顺序处理,没有这两个注解的最后处理。

好了,到这边BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已经处理完了。后面我们会拿ConfigurationClassPostProcessor 这个特殊的BeanDefinitionRegistryPostProcessor做列子讲下具体流程,这边只是介绍BeanFactoryPostProcessor的调用机制。

到此这篇关于Spring的BeanFactoryPostProcessor接口的文章就介绍到这了,更多相关Spring BeanFactoryPostProcessor接口内容请搜索社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持社区!

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1060120
帖子:212021
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP