spring5/springboot2源码学习 -- BeanFactoryPostProcessor相关

这个东西是干嘛的

可以用于自定义对BeanDefinition(而不是具体的bean)的修改,比如:PropertySourcesPlaceholderConfigurer就是用于解决类似@Value(“${…}”)这种占位符的
其实还可以添加BeanDefinition,大家可以思考一下spring啥时候需要添加BeanDefinition…

BeanFactoryPostProcessor接口

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    /**
     * 在ApplicationContext实例化后修改其内部的BeanFactory.
     * 所有的BeanDefinition都已经加载了,但是bean都还没有实例化
     * 可以在这里修改BeanDefinition的各种属性(spring源码注释的翻译)
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

它还有一个比较重要的子接口:BeanDefinitionRegistryPostProcessor:

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

大家应该思考了一会上面那个问题,现在揭晓答案(可能只是答案之一):在有@Configuration注解的时候,因为一般情况下我们用基于注解的方式去注册bean,都是一一对应的,比如你在一个类上加@Component,只会生成一个BeanDefinition。只有较新的JavaConfig的这一套@Configuration/@Bean会通过一个类产生出多个BeanDefinition。
Spring中用户处理@Configuration的是ConfigurationClassPostProcessor,它就是BeanDefinitionRegistryPostProcessor的实现类

Spring中对BeanFactoryPostProcessor的调用

先说一下大致的处理流程:
总体上来说是先调用实现BeanDefinitionRegistryPostProcessor的,再调用实现BeanFactoryPostProcessor的;
每一类自己的调用顺序是按照: 手动注册进去的(.addBeanFactoryPostProcessor()方法) -> 实现了PriorityOrdered接口的 -> 实现Ordered接口的 -> 剩下的

就在ApplicationContext的refresh方法中:

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);

        try {
            postProcessBeanFactory(beanFactory);

            //从方法名应该也能看出来,就是它了
            invokeBeanFactoryPostProcessors(beanFactory);

            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        } catch (BeansException ex) {

            destroyBeans();

            cancelRefresh(ex);

            throw ex;
        } finally {
            resetCommonCaches();
        }
    }
}

点进去能看到,其实真正的处理是:

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

继续进入:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    //用于避免BeanDefinitionRegistryPostProcessor被处理两遍
    Set<String> processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry) {//判断BeanFactory的类型,如果没有实现BeanDefinitionRegistry,就没必要走BeanDefinitionRegistryPostProcessor了
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        //手动注册进来的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
        //手动注册进来的BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();

        //处理手动注册进来的BeanFactoryPostProcessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                //这里这是调用呢BeanDefinitionRegistryPostProcessor里的方法,并没有调用BeanFactoryPostProcessor里的方法
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }

        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        //首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        //这几句都是重复的 排序 -> 调用 -> 从当前处理list中清除(后面会直接省略掉...)
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // 调用实现了Ordered接口的
        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);
            }
        }
        //同上的四步

        // 调用剩下的
        // 可能大家会有问题,为啥上面都是一层循环,这里却是两层
        // 答案就是BeanDefinitionRegistryPostProcessor是可以自己再创建一个BeanDefinitionRegistryPostProcessor的BeanDefinition然后放到BeanFactory中去的
        // 所以就加了一层循环,用于确保后来生成的那些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;
                }
            }
            //同上的四步
        }

        //上面回调的是BeanDefinitionRegistryPostProcessor的方法,这里调的是BeanFactoryPostProcessor的方法
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    //BeanFactoryPostProcessor像之前一样的流程再走一遍
    //请注意这里只有实现priorityOrdered才是直接获取到具体事例,其它两种都是这保留了一个name
    //原因也是在于,BeanFactory.getBean()被调用时,就意味着bean被真的实例化出来了
    //更高优先级的BeanFactoryPostProcessor可能会对后面的BeanFactoryPostProcessor的BeanDefinition有影响
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            //跳过已经在BeanDefinitionRegistryPostProcessor中处理过的
        } 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);
        }
    }

    //跟BeanDefinitionRegistryPost类似的过程,分别调用各个postProcessor


    //清除一下元数据的缓存,因为这些postProcessor可能已经修改了这些值
    beanFactory.clearMetadataCache();
}

注意点

BeanFactoryPostProcessor的调用具体是在AC的refresh()方法中,所以如果是自己想要定义一个BeanFactoryPostProcessor并添加到AC中,那要在refresh()这个方法被调用之前,否则是不会有效的。
还有refresh()方法,是很可能会被间接调用的,比如对于AnnotationConfigApplicationContext,只要实例化的时候加了参数,那么refresh就会被调用

结语

spring5的源码才看一点,PropertySourcesPlaceholderConfigurer/ConfigurationClassPostProcessor的分析放到后面吧…

(水平有限,最近在看spring源码,分享学习过程,希望对各位有点微小的帮助。
如有错误,请指正~)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值