• 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    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;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    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"));
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    控制台

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

    通过自定义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;
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    注册并调用BeanFactoryPostProcessors

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
       PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    }
    
    • 1
    • 2
    • 3

    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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136

    BeanDefinitionRegistryPostProcessor

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

    public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
       void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    
    }
    
    • 1
    • 2
    • 3
    • 4

    总结

    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
  • 相关阅读:
    API接口开发采集淘宝商品详情页数据优惠券sku价格销量信息等可支持高并发接入演示
    C#常识篇(二)
    序列模型(一)- 循环序列模型
    《牛客题霸-算法篇》刷题之NC57 反转数字
    入职半年,加薪50%,这4类人是如何搭建办公知识体系的?
    Linux的 Bash 简介和使用方法
    mysql数据增删改
    NonlinearFactorGraph.h/NonlinearFactorGraph.cpp
    磨金石教育摄影技能干货分享|古风人像拍摄要注意哪些问题
    VulnHub DC-6
  • 原文地址:https://blog.csdn.net/u013493841/article/details/125632506