總結Spring中工廠後處理器

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/chyohn/article/details/55101630

工廠處理器是一種特殊的Bean,這種Bean並不對外提供服務,它甚至可以無需id屬性,它主要負責對容器本身進行某些特殊的處理。Spring中有兩類工廠後處理器,一個是BeanFactoryPostProcessor,它是所有工廠後處理器的頂層接口;另一個是BeanDefinitionRegistryPostProcessor,它繼承自BeanFactoryPostProcessor,設計它的目的是使用它向Bean註冊表(一個BeanDefinitionRegistry 對象)中註冊bean的配置信息——一個BeanDefinition對象。

BeanFactoryPostProcessor的定義

Spring工廠後處理器的頂層接口org.springframework.beans.factory.config.BeanFactoryPostProcessor的定義如下。

public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

postProcessBeanFactory方法在BeanFactory對象實例化完成後,當所有的bean的BeanDefinition對象加載完成時(即,所有bean的配置信息都已經註冊到bean註冊表中)被調用。它允許覆蓋或者設置bean的屬性值,甚至是立即實例化bean,比如實例化bean後處理器對象。

BeanDefinitionRegistryPostProcessor的定義

Spring還定義了一個工廠後處理器接口,那就是org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor,該接口繼承了BeanFactoryPostProcessor。下面是它的源碼定義。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean definition registry after its
     * standard initialization. All regular bean definitions will have been loaded,
     * but no beans will have been instantiated yet. This allows for adding further
     * bean definitions before the next post-processing phase kicks in.
     * @param registry the bean definition registry used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

postProcessBeanDefinitionRegistry方法用向bean註冊表BeanDefinitionRegistry對象(一般是Spring默認的BeanFacotry對象——DefaultListableBeanFactory)中註冊bean的配置信息,即註冊BeanDefintion對象。

兩類工廠bean的執行順序

BeanFactoryPostProcessor的postProcessBeanFactory方法在所有的bean的BeanDefinition對象加載到bean註冊表中後被調用,而BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法用於向bean註冊表中註冊BeanDefinition對象。因此,這兩個方法的執行順序有嚴格的要求,下面我們通過Spring4的源碼解釋這個流程。

Spring4執行把通過PostProcessorRegistrationDelegate的靜態方法invokeBeanFactoryPostProcessors方法執行工廠後處理器的相關方法,此方法的代碼如下。(這段代碼有點長,看我的註釋就是了)

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

         // 首先執行BeanDefinitionRegistryPostProcessors
        Set<String> processedBeans = new HashSet<String>();

        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
            List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                    new LinkedList<BeanDefinitionRegistryPostProcessor>();
            // 遍歷容器中的工廠後處理器
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryPostProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    // 執行BeanDefinitionRegistryPostProcessor的
                    // ->postProcessBeanDefinitionRegistry方法
                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryPostProcessors.add(registryPostProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

             // 獲取並執行bean工廠中定義的BeanDefinitionRegistryPostProcessor對象,這裏分爲三步,如下。
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

            // 首先,執行實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor對象
            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);
            invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);

            // 然後,執行實現了Ordered接口的BeanDefinitionRegistryPostProcessor對象
            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);

            // 最後執行其它的BeanDefinitionRegistryPostProcessor對象
            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;
                    }
                }
            }

            // 執行BeanDefinitionRegistryPostProcessor工廠後處理器的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
            // 執行容器中普通的工廠後處理器的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        } else {
            // 執行容器中的bean工廠後處理器的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // 獲取定義在bean工廠中的bean工廠後處理器,下面執行postProcessBeanFactory方法也分成三步,如下。
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // 把bean工廠後處理器按PriorityOrdered、Ordered和其他來分類
        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)) {
                // 排除前面已經執行了的後處理器
            }
            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);
            }
        }

        // 首先執行實現了PriorityOrdered接口的後處理器
        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // 然後執行實現了Ordered接口的後處理器
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(beanFactory, orderedPostProcessors);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        //  最後執行其他的後處理器
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // 清除工廠中的元數據緩存
        beanFactory.clearMetadataCache();
    }
    /**
     * 執行給定的BeanDefinitionRegistryPostProcessor beans.
     */
    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }
    /**
    * 執行給定的bean工廠
    **/
    private static void invokeBeanFactoryPostProcessors(
            Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }

上面的執行流程用圖表達如下。
這裏寫圖片描述

上圖很明顯的表達了bean工廠後處理器的執行順序,但這裏還有兩點需要說明的。

a. 爲什麼要先執行BeanDefinitionRegistryPostProcessor?因爲實現BeanDefinitionRegistryPostProcessor 接口的後處理器可以在bean工廠創建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類就是這樣一種工廠後處理器,它主要把被@Configuration註解的類中定義的bean信息轉換成BeanDefinition對象,並註冊到bean工廠中。

b. 這個流程中有一個很明顯的規定就是,不管是什麼工廠後處理器,都必須先執行容器中的工廠後處理器後,才執行bean工廠中的工廠後處理器。這裏的容器中的工廠後處理器是指ApplicationContext對象所持有的未註冊到bean工廠中的。bean工廠中的工廠後處理器是指註冊到BeanFactory對象中的後處理器。

BeanDefinitionRegistryPostProcessor接口的實現類

spring-context-x.x.x模塊下的org.springframework.context.annotation.ConfigurationClassPostProcessor後處理器,用於加載基於java類配置的bean。

mybatis-spring包中的org.mybatis.spring.mapper.MapperScannerConfigurer:用於掃描指定包下的mapper接口。

BeanFactoryPostProcessor接口的實現類

spring-beans-x.x.x模塊下的PropertyOverrideConfigurer:加載屬性文件中信息直接覆蓋Spring配置文件中的元數據。

spring-beans-x.x.x模塊下PropertyPlaceholderConfigurer及其子類PreferencesPlaceholderConfigurer:負責讀取properties屬性文件裏的屬性值,並將這些屬性值設置成Spring配置文件的元數據。

spring-context-x.x.x模塊下PropertySourcesPlaceholderConfigurer:和PropertyPlaceholderConfigurer的作用一樣,不過前者是spring3.1後<context:property-placeholder/>默認加載。後者是3.1以前默認加載的。

關於上面3個與加載屬性文件相關的後處理器如何被引入到Spring容器中,請見解析context命名空間之property-placeholder和property-override標籤

spring-beans-x.x.x模塊下的CustomScopeConfigurer:用於向BeanFactory中註冊自定義bean作用域Scope對象。

spring-beans-x.x.x模塊下的CustomEditorConfigurer:用於向BeanFactory中註冊自定義的PropertyEditorRegistrar對象和PropertyEditor對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章