Bootstrap

Spring 源码分析-简单示例带你了解BeanFactoryPostProcessor

概述

BeanFactoryPostProcessor 是 Spring针对BeanFactory做的扩展,可以对bean的定义(配置元数据进行处理)。也就是说SpringIoc容器允许BeanFactoryPostProcessor 在容器实际实例化任何其他的bean之前读取配置元数据,并有可能修改它。也就是说,我们根据我们的需要对 BeanDefinition 进行修改。

先看BeanFactoryPostProcessor的使用效果

这是一个《Spring源码深度解析》书中的示例,实现一个BeanFactoryPostProcessor,来修改bean中定义的特定属性值,实现一个“屏蔽” 效果。

bean xml 配置文件

<bean id="bfpp" class="com.at.spring.spring2021.ObscenityRemovingBeanFactoryPostProcessor">

   <property name="obscenties">
      <set>
         <value>bollockes</value>
      </set>
   </property>
</bean>

<bean id="car" class="com.at.spring.beans.autowire.Car"
     p:brand="bollockes" p:price="4500000" scope="singleton" lazy-init="false">

</bean>

ObscenityRemovingBeanFactoryPostProcessor.java

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionVisitor;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.StringValueResolver;

import java.util.HashSet;
import java.util.Set;

public class ObscenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    private Set<String> obscenties;

    public ObscenityRemovingBeanFactoryPostProcessor() {
        obscenties = new HashSet<>(0);
    }

    public Set<String> getObscenties() {
        return obscenties;
    }

    public void setObscenties(Set<String> obscenties) {
        this.obscenties.clear();
        for (String obscenty : obscenties) {
            this.obscenties.add(obscenty.toUpperCase());
        }
    }

    public ObscenityRemovingBeanFactoryPostProcessor(Set<String> obscenties) {
        this.obscenties = obscenties;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        String[] beanNames = beanFactory.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
            StringValueResolver valueResolver = new StringValueResolver() {
                @Override
                public String resolveStringValue(String strValue) {
                    if (isObscene(strValue)) {
                        return "********";
                    }
                    return strValue;
                }
            };
            BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
            visitor.visitBeanDefinition(bd);
        }

    }

    public boolean isObscene(Object value) {
        String potentialObsenity = value.toString().toUpperCase();
        return this.obscenties.contains(potentialObsenity);
    }
}

Car.java

public class Car {
   
   private String brand;
   private double price;
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   @Override
   public String toString() {
      return "Car [brand=" + brand + ", price=" + price + "]";
   }


   public Car() {
      System.out.println("Car 无参构造方法");
   }

   public Car(String brand, double price) {
      System.out.println("Car 有参构造方法");
      this.brand = brand;
      this.price = price;
   }
}

main方法

public static void main(String[] args) throws IOException {
    ClassPathXmlApplicationContext classPathXmlApplicationContext = new     ClassPathXmlApplicationContext("beans-beanFactoryPostProcessor.xml");
    BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor)         classPathXmlApplicationContext.getBean("bfpp");
    System.out.println(classPathXmlApplicationContext.getBean("car"));

}

控制台

Car 无参构造方法
Car [brand=********, price=4500000.0]

通过自定义BeanFactoryPostProcessor实现类,当Car 这个 bean中属性 brand 是 obscenties 定义的字符串时,则使用 “*******” 代替。

扩展点

在Spring容器生命周期过程中,有这样一个处理,invokeBeanFactoryPostProcessors(beanFactory), 这里就是加载BeanFactoryPostProcessor 并调用的逻辑所在。

AbstractApplicationContext类

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        // 1. Spring 上下文准备阶段
        this.prepareRefresh();
        // 2. BeanFactory创建阶段 
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        // 3. BeanFactory准备阶段
        this.prepareBeanFactory(beanFactory);

        try {
            // 4. BeanFactory 后置处理阶段
            this.postProcessBeanFactory(beanFactory);
            // 5. BeanFactory注册BeanFactoryPostProcessor阶段
            this.invokeBeanFactoryPostProcessors(beanFactory);
            // 6. 注册BeanPostProcessor阶段
            this.registerBeanPostProcessors(beanFactory);
            // 7. 初始化消息源
            this.initMessageSource();
            // 8. 初始化自定义事件广播器
            this.initApplicationEventMulticaster();
            // 9. Spring 应用上下文刷新阶段,由子类实现
            this.onRefresh();
            // 10. Spring事件监听注册阶段
            this.registerListeners();
            // 11. 实例化剩余的(非lazy init)的单例bean
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var5) {
            this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
            this.destroyBeans();
            this.cancelRefresh(var5);
            throw var5;
        }

    }
}
注册并调用BeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

PostProcessorRegistrationDelegate 类

具体关键代码含义可以看在源码中添加的注释:

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // 首先调用 BeanDefinitionRegistryPostProcessors 
   // Invoke BeanDefinitionRegistryPostProcessors first, if any.
   Set<String> processedBeans = new HashSet<String>();
   // 判断 beanFactory 是否是 BeanDefinitionRegistry 类型
   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); // 提前创建一个集合,用于后边存放
      List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
            new LinkedList<BeanDefinitionRegistryPostProcessor>();
      // 查找 beanFactory 中存放的 BeanFactoryPostProcessor
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryPostProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            registryPostProcessor.postProcessBeanDefinitionRegistry(registry); // 执行其中的方法
            registryPostProcessors.add(registryPostProcessor); // add 到 registryPostProcessors
         }
         else {
            regularPostProcessors.add(postProcessor); // 不是 BeanDefinitionRegistryPostProcessor 类型,所以add 到 常规的 regularPostProcessors
         }
      }
      // 不要在这里初始化FactoryBeans: 我们需要让所有常规bean保持未初始化状态,以便让bean工厂后处理器应用于它们
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the bean factory post-processors apply to them!
      // Separate between BeanDefinitionRegistryPostProcessors that implement
      // PriorityOrdered, Ordered, and the rest.
      // 查找 BeanDefinitionRegistryPostProcessor 类型的bean
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      // 首先调用使用了 PriorityOrdered 的  BeanDefinitionRegistryPostProcessor
      // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
      List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
      for (String ppName : postProcessorNames) {
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
      registryPostProcessors.addAll(priorityOrderedPostProcessors);
      // 优先进行调用 PriorityOrdered (PriorityOrdered 优先级大于Ordered)
      invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
      // 其次调用 Ordered
      // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
      for (String ppName : postProcessorNames) {
         if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(beanFactory, orderedPostProcessors);
      registryPostProcessors.addAll(orderedPostProcessors);
      invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
      // 最后调用其他的 BeanDefinitionRegistryPostProcessors
      // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
      boolean reiterate = true;
      while (reiterate) {
         reiterate = false;
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName)) {
               BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
               registryPostProcessors.add(pp);
               processedBeans.add(ppName);
               pp.postProcessBeanDefinitionRegistry(registry);
               reiterate = true;
            }
         }
      }
      // 调用所有的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法
      // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
      invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
   }

   else {
      // 调用所有的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法
      // Invoke factory processors registered with the context instance.
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let the bean factory post-processors apply to them!
   String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

   // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
   // Ordered, and the rest.
   List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   List<String> orderedPostProcessorNames = new ArrayList<String>();
   List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
   for (String ppName : postProcessorNames) {
      // 查找使用了实现了 PriorityOrdered 的PostProcessor
      if (processedBeans.contains(ppName)) {
          // 如果在processedBeans集合中,说明一件在前面的代码中处理过了
         // skip - already processed in first phase above
      }
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }  // 其次调用 Ordered
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
   sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
   List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(beanFactory, orderedPostProcessors);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

   // Finally, invoke all other BeanFactoryPostProcessors.
   List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
   for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   } 
   // 最后调用没有指定顺序的BeanFactoryPostProcessor
   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();
}
BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的子类,自己添加了postProcessBeanDefinitionRegistry 方法,更加便于对BeanDefinition的扩展。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

总结

  1. 实现了 BeanFactoryPostProcessor 接口,就可以在spring加载bean的生命周期中,实例化 bean前 可以对BeanDefinition 进行修改或处理。
  2. 这个地方千万不能对bean进行实例化操作,因为会发生意想不到的结果。来自源码中的注释:but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects.
  3. 在调用BeanFactoryPostProcessor 提供的方法时,根据PriorityOrdered -> Order -> 普通的 这个的顺序来执行postProcessBeanFactory 方法。

参考资料

  • https://mp.weixin.qq.com/s/CtGguqqDVSFfRxXfJKPR1w
  • http://www.itsoku.com/article/323
  • https://my.oschina.net/u/4072299/blog/4433981
;