ClassPathXmlApplicationContext源码解析三:BFPP

来源:互联网 发布:网络交友的利弊 编辑:程序博客网 时间:2024/06/05 10:29

本文引自我的个人博客: 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}

原创粉丝点击