ClassPathXmlApplicationContext源码解析三:BFPP

本文引自我的个人博客: sunmingshuai.coding.me

让我们再回到refresh()方法 继续往下看 看下面两个方法

...
//如果是XmlWebApplicationContext的话 会注册一些BPP 例如ServletContextAwareProcessor
// 这里留空
                postProcessBeanFactory(beanFactory);

                // spring扩展的实现(容器级别) BeanFactoryPostProcessor 在实例化任何用户定义的bean之前 会首先调用BFPP的接口方法
                // 常见的BFPP:PropertyPlaceholderConfigurer
                invokeBeanFactoryPostProcessors(beanFactory);
...
//BFPP接口
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

invokeBeanFactoryPostProcessors方法逻辑就比较简单了 就是调用BFPP的接口方法 这些BFPP的来源途径有
1. 硬编码方式
2. 用户配置
3. 容器自身为了完成某些功能添加
这些BFPP支持排序 排序大的先调用

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<String>();
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            //BFPP(postProcessBeanFactory)
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
            //BeanDefinitionRegistryPostProcessor 是BFPP的子类
            List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                    new LinkedList<BeanDefinitionRegistryPostProcessor>();
            //硬编码方式加入的BFPP 例如通过addXXX
            for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryPostProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryPostProcessors.add(registryPostProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }
            //处理配置中的BDRPP
            Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
                    beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
            List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
                    new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
            OrderComparator.sort(registryPostProcessorBeans);
            for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
            processedBeans.addAll(beanMap.keySet());
        }
        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), 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) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

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

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

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    }

上面的代码逻辑很简单 就不再解释了 下面我们介绍一个常用的BFPP: PropertyPlaceholderConfigurer 先看一下常用的配置

<bean name="official" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="order" value="100" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="locations">
            <list>
                <value>file:${user.home}/config/official.properties</value>
            </list>
        </property>
    </bean>

PropertyPlaceholderConfigurer是用来在BeanClass实例化之前调用的,通过载入指定properties文件,替换诸如${}这种形式的变量.PropertyPlaceholderConfigurer可以用来区分生产环境与开发环境 例如我们在生产环境部署official.properties文件 这个文件中的参数值 如jdbc.url 代表的是生产环境的value 然后我们在开发环境中部署developer.properties文件 这个文件中的参数值 如jdbc.url 代表的是开发环境的value 这样我们的项目发布在什么环境读取的就是相应环境的变量值 不需要每次改代码去解决
PropertyPlaceholderConfigurer的功能实现我们大概能猜的到 首先肯定是先获取这个Bean 这个步骤会涉及到Bean的实例化 属性填充等操作 我们暂且略过这个步骤 后面会详细介绍 然后就是读取配置的properties文件 再然后就是替换Bean属性中的${xx}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值