zoukankan      html  css  js  c++  java
  • Spring源码学习笔记(七、Spring启动流程解析:调用后处理器)

    目录:

    • 准备工作
    • BeanFactory后处理源码解析:invokeBeanFactoryPostProcessors

    准备工作

    在了解BeanFactory后处理源码前首先我们需要先了解几个东西:

    1、BeanPostProcessor、BeanFactoryPostProcessor区别

    这两个从名字来看可能很相似,但处理的事是完全不一样的

    • BeanPostProcessor是针对bean实例化后做的定制处理,会在bean初始化前后做处理。
    • BeanFactoryPostProcessor是用来操作bean元数据的,也可以说是操作配置文件的,是在定义bean阶段的后置处理

    你可以这样理解,bean就是你的孩子,BeanPostProcessor就是你在你孩子出生后给他的一些规划,怎么培养他等等;而BeanFactoryPostProcessor就是你在你孩子出生前给他的一些定制操作,比如网上说的多吃葡萄生出的孩子眼睛大,哈哈哈哈。

    ———————————————————————————————————————————————————————

    2、BeanDefinitionRegistryPostProcessor

    BeanDefinitionRegistryPostProcessor是对标准BeanFactoryPostProcessor的扩展,允许在进行常规BeanFactoryPostProcessor检测之前注册其他Bean定义

    特别是,BeanDefinitionRegistryPostProcessor注册的Bean定义,又定义了BeanFactoryPostProcessor实例。

    ———————————————————————————————————————————————————————

    3、自定义BeanFactoryPostProcessor

    了解了第1、2两个点之后,我们就看看如何自定义BeanFactoryPostProcessor。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
     5 
     6     <bean class="com.jdr.spring.postprocessor.bean.Car" name="car">
     7         <property name="name" value="benz"/>
     8     </bean>
     9 
    10     <bean class="com.jdr.spring.postprocessor.CarBeanFactoryPostProcess1" name="carBeanFactoryPostProcess1">
    11         <property name="order" value="0"/>
    12     </bean>
    13 
    14     <bean class="com.jdr.spring.postprocessor.CarBeanFactoryPostProcess2" name="beanFactoryPostProcess2">
    15         <property name="order" value="1"/>
    16     </bean>
    17 
    18     <bean class="com.jdr.spring.postprocessor.MobileBeanFactoryPostProcessor" name="mobileBeanFactoryPostProcessor"/>
    19 
    20 </beans>
     1 public class Car {
     2 
     3     private String name;
     4     private String color;
     5 
     6 //  getter and setter
     7 
     8     public String getName() {
     9         return name;
    10     }
    11 
    12     public void setName(String name) {
    13         this.name = name;
    14     }
    15 
    16     public String getColor() {
    17         return color;
    18     }
    19 
    20     public void setColor(String color) {
    21         this.color = color;
    22     }
    23 }

    配置文件很简单,就是定义了一些bean,以及设置了他们的属性。

    如果我现在就执行的话,肯定能的到Car的name=benz,color=null,如果我们想改变其属性的话就可以通过BeanFactoryPostProcessor来实现,也就是通过BeanFactoryPostProcessor操作元数据。

     1 public class CarBeanFactoryPostProcess1 implements BeanFactoryPostProcessor, Ordered {
     2 
     3     private int order;
     4 
     5     @Override
     6     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
     7         System.out.println("invoke CarBeanFactoryPostProcess1...");
     8         BeanDefinition car = beanFactory.getBeanDefinition("car");
     9         // 重置name属性
    10         car.getPropertyValues().addPropertyValue("name", "BMW");
    11     }
    12 
    13     @Override
    14     public int getOrder() {
    15         return this.order;
    16     }
    17 
    18 //  getter and setter
    19 
    20     public void setOrder(int order) {
    21         this.order = order;
    22     }
    23 }
    24 
    25 public class CarBeanFactoryPostProcess2 implements BeanFactoryPostProcessor, Ordered {
    26 
    27     private int order;
    28 
    29     @Override
    30     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    31         System.out.println("invoke CarBeanFactoryPostProcess2...");
    32         BeanDefinition car = beanFactory.getBeanDefinition("car");
    33         // 添加color属性
    34         car.getPropertyValues().addPropertyValue("color", "red");
    35     }
    36 
    37     @Override
    38     public int getOrder() {
    39         return this.order;
    40     }
    41 
    42 //  getter and setter
    43 
    44     public void setOrder(int order) {
    45         this.order = order;
    46     }
    47 }

    经过这一番操作,就将元数据修改了,name=BMW,color=red。

    同样的,我们可以通过实现BeanDefinitionRegistryPostProcessor来定义bean,而不是通过xml来配置,如下:

     1 public class MobileBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
     2 
     3     @Override
     4     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
     5         // 定义bean
     6         System.out.println("invoke MobileBeanFactoryPostProcessor postProcessBeanDefinitionRegistry...");
     7         BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Mobile.class);
     8         registry.registerBeanDefinition("mobile", builder.getBeanDefinition());
     9     }
    10 
    11     @Override
    12     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    13         // 定义bean后的处理
    14         System.out.println("invoke MobileBeanFactoryPostProcessor postProcessBeanFactory...");
    15         BeanDefinition mobile = beanFactory.getBeanDefinition("mobile");
    16         mobile.getPropertyValues().addPropertyValue("number", "123456");
    17     }
    18 }

    4、先有bean的定义,还是bean的实例化

    毋庸置疑,肯定只有bean被定义好了后才能正常实例化bean;也就是说BeanDefinitionRegistryPostProcessor肯定优先于BeanFactoryPostProcessor执行(这个等会会在源码里看到)。

    5、PriorityOrdered和Ordered

    Priority定义如下,仅仅是继承Ordered,但含义却不一样,是优先于Ordered的排序。

    1 public interface PriorityOrdered extends Ordered {
    2 }

    BeanFactory后处理源码解析:invokeBeanFactoryPostProcessors

    这部分的源码非常简单,很容易理解。

      1 public static void invokeBeanFactoryPostProcessors(
      2         ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
      3 
      4     // 记录以及执行过的BeanDefinitionRegistryPostProcessors,以免重复执行
      5     Set<String> processedBeans = new HashSet<String>();
      6 
      7     // 若beanFactory是实现了BeanDefinitionRegistry
      8     // 其实也就是指DefaultListableBeanFactory或者GenericApplicationContext
      9     if (beanFactory instanceof BeanDefinitionRegistry) {
     10         BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
     11         // 存放普通的BeanFactoryPostProcessor
     12         List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
     13         // 存放已经执行注册函数的BeanDefinitionRegistryPostProcessor
     14         List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
     15 
     16         // 上面的准备工作中已经提到BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展,提供了注册bean的功能
     17         // 所以说这段代码的含义就是,若postProcessor是BeanDefinitionRegistryPostProcessor的话先执行注册的函数,再将其放到registryProcessors中
     18         // 否则将其放到常规的,仅提供了后置处理操作的regularPostProcessors中
     19         for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
     20             if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
     21                 BeanDefinitionRegistryPostProcessor registryProcessor =
     22                         (BeanDefinitionRegistryPostProcessor) postProcessor;
     23                 registryProcessor.postProcessBeanDefinitionRegistry(registry);
     24                 registryProcessors.add(registryProcessor);
     25             }
     26             else {
     27                 regularPostProcessors.add(postProcessor);
     28             }
     29         }
     30 
     31         // 当前要注册的BeanDefinitionRegistryPostProcessor集合
     32         List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
     33 
     34         // 拿出beanFactory中所有类型为BeanDefinitionRegistryPostProcessor的beanName
     35         // 如果其实现了PriorityOrdered接口,就先将其放入到currentRegistryProcessors中
     36         String[] postProcessorNames =
     37                 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     38         for (String ppName : postProcessorNames) {
     39             if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
     40                 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     41                 processedBeans.add(ppName);
     42             }
     43         }
     44         // 执行了currentRegistryProcessors的排序、添加到已注册集合中、执行注册函数、清空集合操作
     45         sortPostProcessors(currentRegistryProcessors, beanFactory);
     46         registryProcessors.addAll(currentRegistryProcessors);
     47         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
     48         currentRegistryProcessors.clear();
     49 
     50         // 步骤同上,只是这里只会执行实现了Ordered接口的postProcessorNames
     51         // 这里也可以证实了我“准备工作”中所提到了:PriorityOrdered优先于Ordered的执行
     52         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     53         for (String ppName : postProcessorNames) {
     54             if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
     55                 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     56                 processedBeans.add(ppName);
     57             }
     58         }
     59         sortPostProcessors(currentRegistryProcessors, beanFactory);
     60         registryProcessors.addAll(currentRegistryProcessors);
     61         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
     62         currentRegistryProcessors.clear();
     63 
     64         // 最后一步,调用其它的BeanDefinitionRegistryPostProcessor,也就是未实现排序接口的
     65         boolean reiterate = true;
     66         while (reiterate) {
     67             reiterate = false;
     68             postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
     69             for (String ppName : postProcessorNames) {
     70                 if (!processedBeans.contains(ppName)) {
     71                     currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
     72                     processedBeans.add(ppName);
     73                     reiterate = true;
     74                 }
     75             }
     76             sortPostProcessors(currentRegistryProcessors, beanFactory);
     77             registryProcessors.addAll(currentRegistryProcessors);
     78             invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
     79             currentRegistryProcessors.clear();
     80         }
     81 
     82         // 当所有的已注册完毕,就先调用registryProcessors的bean后置处理回调,再调regularPostProcessors的后置回调
     83         invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
     84         invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
     85     }
     86 
     87     else {
     88         // 如果不是BeanDefinitionRegistry,说明不会注册bean,直接调用bean的后置处理即可
     89         invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
     90     }
     91 
     92     // 这里之后的代码和上面类似,只不过此处只处理BeanFactoryPostProcessor
     93     // 也是根据优先级来,PriorityOrdered > Ordered > Normal
     94     // 并执行他们的bean后置处理函数
     95     // 我相信只要你把前面的代码读懂了,这部分是非常容易理解的,哈哈哈哈哈哈
     96     String[] postProcessorNames =
     97             beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
     98 
     99     // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    100     // Ordered, and the rest.
    101     List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    102     List<String> orderedPostProcessorNames = new ArrayList<String>();
    103     List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    104     for (String ppName : postProcessorNames) {
    105         if (processedBeans.contains(ppName)) {
    106             // skip - already processed in first phase above
    107         }
    108         else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    109             priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    110         }
    111         else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    112             orderedPostProcessorNames.add(ppName);
    113         }
    114         else {
    115             nonOrderedPostProcessorNames.add(ppName);
    116         }
    117     }
    118 
    119     // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    120     sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    121     invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    122 
    123     // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    124     List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    125     for (String postProcessorName : orderedPostProcessorNames) {
    126         orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    127     }
    128     sortPostProcessors(orderedPostProcessors, beanFactory);
    129     invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    130 
    131     // Finally, invoke all other BeanFactoryPostProcessors.
    132     List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    133     for (String postProcessorName : nonOrderedPostProcessorNames) {
    134         nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    135     }
    136     invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    137 
    138     // Clear cached merged bean definitions since the post-processors might have
    139     // modified the original metadata, e.g. replacing placeholders in values...
    140     beanFactory.clearMetadataCache();
    141 }
  • 相关阅读:
    使用C#抓取网页内容并分析获取数据
    C#获取网页内容的三种方式
    jquery各种版本判断checkbox checked
    C#接口作为返回值
    Sql语句用string.Format格式化
    c# empty和null区别
    not is null 和 is not null
    每一个班级中每一门课程获得最高分的学生的学号
    hdu 2647
    hdu 3342
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/12988269.html
Copyright © 2011-2022 走看看