Spring4.3.x 容器的刷新過程

概述


Spring容器體系的繼承結構圖如下。

這裏寫圖片描述

從圖中可以看出抽象類AbstractApplicationContext是所有容器類的父類。AbstractApplicationContext實現了它繼承的所有接口方法,並定義了三個用於管理BeanFactory對象的抽象方法,如下

    //---------------------------------------------------------------------
    // Abstract methods that must be implemented by subclasses
    //---------------------------------------------------------------------

    /**
     * Subclasses must implement this method to perform the actual configuration load.
     * The method is invoked by {@link #refresh()} before any other initialization work.
     * <p>A subclass will either create a new bean factory and hold a reference to it,
     * or return a single BeanFactory instance that it holds. In the latter case, it will
     * usually throw an IllegalStateException if refreshing the context more than once.
     * @throws BeansException if initialization of the bean factory failed
     * @throws IllegalStateException if already initialized and multiple refresh
     * attempts are not supported
     */
    protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

    /**
     * Subclasses must implement this method to release their internal bean factory.
     * This method gets invoked by {@link #close()} after all other shutdown work.
     * <p>Should never throw an exception but rather log shutdown failures.
     */
    protected abstract void closeBeanFactory();

    /**
     * Subclasses must return their internal bean factory here. They should implement the
     * lookup efficiently, so that it can be called repeatedly without a performance penalty.
     * <p>Note: Subclasses should check whether the context is still active before
     * returning the internal bean factory. The internal factory should generally be
     * considered unavailable once the context has been closed.
     * @return this application context's internal bean factory (never {@code null})
     * @throws IllegalStateException if the context does not hold an internal bean factory yet
     * (usually if {@link #refresh()} has never been called) or if the context has been
     * closed already
     * @see #refreshBeanFactory()
     * @see #closeBeanFactory()
     */
    @Override
    public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

小技巧:告訴大家如何查看一個抽象類未實現的接口方法有哪些,比如上面的AbstractApplicationContext抽象類。我創建了一個MyApplicationContext 類,如果未實現任何方法,IDE會提醒我實現父類中未實現的方法,代碼如下。

public class MyApplicationContext extends AbstractApplicationContext {
    @Override
    protected void refreshBeanFactory() throws BeansException, IllegalStateException {

    }

    @Override
    protected void closeBeanFactory() {

    }

    @Override
    public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException {
        return null;
    }
}

迴歸正題,Spring容器在初始化的時候都會執行一個方法來結束初始化,那就是refresh()方法,此方法定義在接口ConfigurableApplicationContext中,並且抽象類AbstractApplicationContext實現了它,代碼如下

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 爲容器的刷新做準備工作,設置啓動日期,更新活動標誌,加載屬性資源
            prepareRefresh();

            // 獲取最新的bean工廠對象。
            // 要求子類刷新自身持有的bean工廠對象
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 在容器使用bean工廠之前,設置bean工廠
            // 主要是添加特定的bean後處理器
            prepareBeanFactory(beanFactory);

            try {
                // 鉤子方法,允許在子類中bean工廠做進一步的處理
                // 子類可以根據自身需要,添加更多的bean後處理器
                postProcessBeanFactory(beanFactory);

                // 在上下文容器中執行所有註冊了的bean工廠後處理器
                // 執行步驟:1. 在bean工廠中找到所有實現了BeanFactoryPostProcessor的對象
                // ->2. 執行所有bean工廠後處理器的postProcessBeanFactory方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // 把所有用戶配置的bean後處理器添加到bean工廠中
                registerBeanPostProcessors(beanFactory);

                // 初始化國際化消息對象,默認爲DelegatingMessageSource
                initMessageSource();

                // 初始化事件傳播器,默認爲SimpleApplicationEventMulticaster
                initApplicationEventMulticaster();

                // 鉤子方法,初始化其他特定的bean
                onRefresh();

                // 註冊用戶指定的和容器創建時添加的監聽器
                registerListeners();

                // 初始化所有剩下的單例非延遲bean
                finishBeanFactoryInitialization(beanFactory);

                // 完成刷新,包括髮布容器刷新事件
                finishRefresh();
            } catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                /// 銷燬所有已經創建好的bean,以防止內存浪費
                destroyBeans();

                // 重置活動標誌
                cancelRefresh(ex);

                throw ex;
            } finally {
                // 重置反射緩存
                resetCommonCaches();
            }
        }
    }

refresh方法的設計使用了模板方法設計模式,它設定了容器刷新的流程,並把特定階段的執行延遲到子類中執行,比如bean工廠的創建。它還在特定的階段提供鉤子方法,以方便子類根據自身需要進一步完成更多的操作。下面我們一步一步的探討refresh方法的執行流程。下圖是它的一個大概流程圖。

refresh方法在容器的基本配置完成後被調用,它是spring容器初始化過程的主要戰場,下面我們一步一步的探討refresh方法的執行流程。

容器刷新過程


1. 容器刷新前準備

在refresh方法的第1步中,調用AbstractApplicationContext的prepareRefresh()方法完成容器刷新前的準備,代碼如下。

    protected void prepareRefresh() {
        // 設置啓動時間
        this.startupDate = System.currentTimeMillis();

        this.closed.set(false);
        // 把容器設置爲活動
        this.active.set(true);

        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }

        // 鉤子方法,讓子類把所有的stub屬性資源替換成真正需要的屬性資源。
        initPropertySources();

        // 驗證所有被標註爲required的屬性是否可被解析
        getEnvironment().validateRequiredProperties();

        // 允許事件傳播器可用的時候發佈一些事件
        // earlyApplicationEvents存儲需要在事件傳播器可用時發佈的事件
        this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    }

prepareRefresh方法設置容器啓動時間和活動標誌,以及通過調用initPropertySources()方法完成所有的property資源的初始化。initPropertySources()方法是一個空實現,子類可以用它來完成property資源的初始化。例如,下面代碼是在AbstractRefreshableWebApplicationContext類中的實現

    @Override
    protected void initPropertySources() {
        super.initPropertySources();
        ConfigurableEnvironment env = this.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment)env).initPropertySources(
                    this.servletContext, this.servletConfig);
        }
    }

這個方法主要是把ServletContext和ServletConfig對象保存到ConfigurableWebEnvironment環境對象中,以方便環境對象通過getProperty(String key)方法獲取定義在ServletContext和ServletConfig中特定的初始化init-param參數。

2. 創建BeanFactory

執行AbstractApplicationContext的obtainFreshBeanFactory方法,獲取最新的bean工廠對象,代碼如下。

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 刷新bean工廠,是一個抽象方法,由子類實現。
        refreshBeanFactory();
        // 從子類中獲取bean工廠,也是一個抽象方法,由子類實現
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

obtainFreshBeanFactory方法首先調用子類的refreshBeanFactory()方法刷新bean工廠,然後調用子類的getBeanFactory()方法獲取bean工廠。在spring中,refreshBeanFactory()在GenericApplicationContext類和AbstractRefreshableApplicationContext類中都有實現,下面是在AbstractRefreshableApplicationContext類中的實現。

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            // 如果當前上線文容器已有bean工廠
            // 銷燬bean工廠中所有單例bean
            destroyBeans();
            // 關閉已有的bean工廠
            closeBeanFactory();
        }
        try {

            // 創建一個新的bean工廠
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // 自定義bean工廠,包括設置是否允許覆蓋相同ID的bean,是否允許循環引用,等等
            customizeBeanFactory(beanFactory);
            // 加載所有BeanDefinition,是一個抽象方法,有子類實現
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

這個方法裏面,首先把已創建的單例bean銷燬並關閉持有的bean工廠,然後調用createBeanFactory()方法重新創建一個x新的bean工廠代碼如下。最後,並調用子類的loadBeanDefinitions方法把BeanDefinition對象加載到bean工廠中。

    /**
        * 創建一個新的bean工廠
    **/
    protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }

3. 初始化BeanFactory

獲取到BeanFactory對象後,refresh()方法調用AbstractApplicationContext對象的prepareBeanFactory方法和postProcessBeanFactory方法完成bean工廠的初始化。在這個階段,容器中所有的BeanDefinition對象已經被註冊到bean工廠中(除被@Configuration註解的類管理的bean配置外),但是沒有任何一個BeanDefinition所代表的bean被創建,包括工廠後處理器。下面我們看看這個兩個方法的執行情況。

首先,調用prepareBeanFactory方法。這個方法主要功能是,爲bean工廠設置容器的類加載器,以及一些特定的bean後處理器,代碼如下。

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 要求bean工廠和容器共用同一個類加載器
        beanFactory.setBeanClassLoader(getClassLoader());
        // 設置SpEL表達式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
        // 添加Resource編輯器註冊器
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 添加ApplicationContextAwareProcessor後處理器
        // 有可能某些工廠後處理器實現了ApplicationContextAware、ResourceLoaderAware等等如下類似接口
        // ApplicationContextAwareProcessor後處理器就就爲這些接口傳遞相應的對象
        // 因此,在執行工廠後處理器前,必須要設置此後處理器
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        // 檢測用戶是否配置了loadTimeWeaver bean對象
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            // 添加LoadTimeWeaverAwareProcessor後處理器,此後處理器用於向bean中注入LoadTimeWeaver對象
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // 爲類型匹配檢測配置臨時的類加載器
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // 註冊默認的環境bean對象
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        // 註冊OS系統屬性對象
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        // 註冊OS系統環境對象
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

然後,調用postProcessBeanFactory方法。這個方法在AbstractApplicationContext類中的定義如下。

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

postProcessBeanFactory方法被作爲鉤子方法,讓子類在bean工廠初始化的時候根據自身需要,對bean工廠做更多的操作。在web應用中,AbstractRefreshableWebApplicationContext類重寫此方法,代碼如下。

    /**
     * 註冊request/session作用域, 和ServletContextAwareProcessor bean後處理器, .
     */
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 添加ServletContextAwareProcessor後處理器
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

        // 註冊request/session作用域
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        // 把ServletContext對象和ServletConfig對象等以單例bean的形式註冊到bean工廠中
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }

4. 執行bean工廠後處理器的postProcessBeanFactory方法

bean工廠初始化完成後,refresh()方法調用AbstractApplicationContext的invokeBeanFactoryPostProcessors方法完成容器中所有bean工廠後處理器的執行,代碼如下。

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 把執行工廠後處理器的任務委託給PostProcessorRegistrationDelegate
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        // 檢測LoadTimeWeaver對象
        // 聲明:String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

這段代碼主要是把工廠後處理器的任務委託給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>();
            // 遍歷容器中的工廠後處理器,並執行BeanDefinitionRegistryPostProcessors
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryPostProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    // 執行BeanDefinitionRegistryPostProcessors的
                    // ->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工廠後處理器
            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
            // 執行容器中普通的工廠後處理器
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        } else {
            // 執行容器中的bean工廠後處理器
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // 獲取定義在bean工廠中的bean工廠後處理器
        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工廠中的工廠後處理器。

5. 註冊BeanPostProcessor

refresh()方法執行完bean工廠後處理器後,接着調用AbstractApplicationContext的registerBeanPostProcessors方法向bean工廠註冊bean後處理器,registerBeanPostProcessors方法的代碼如下。

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // 把註冊bean後處理器的任務委託給PostProcessorRegistrationDelegate
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }

registerBeanPostProcessors方法把註冊bean後處理器的任務委託給PostProcessorRegistrationDelegate類的registerBeanPostProcessors方法,下面是這個方法的代碼。

    public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        // 從bean工廠中找到所有BeanPostProcessor對象的名稱
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // 註冊BeanPostProcessorChecker後處理器
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // 對所有的bean後處理器根據實現PriorityOrdered,Ordered和其他的進行分組
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
        List<String> orderedPostProcessorNames = new ArrayList<String>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 首先註冊實現了PriorityOrdered接口的bean後處理器
        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // 然後註冊實現了Ordered接口的後處理器.
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(beanFactory, orderedPostProcessors);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 再次,註冊所有普通的後處理器
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // 最後,重新註冊所有內部後處理器
        // ->即實現了MergedBeanDefinitionPostProcessor接口的後處理器
        sortPostProcessors(beanFactory, internalPostProcessors);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }
    /**
     * 註冊指定的BeanPostProcessor beans.
     */
    private static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }

這部分代碼註冊bean後處理器的註冊流程如下。

這裏寫圖片描述

整個流程根據PriorityOrdered、Ordered、非Ordered的順序註冊bean後處理器,最後註冊MergedBeanDefinitionPostProcessor bean後處理器。其中MergedBeanDefinitionPostProcessor會在其他bean後處理器執行前執行它的postProcessMergedBeanDefinition方法。

6. 初始化MessageSource國際化消息

執行AbstractApplicationContext的initMessageSource方法,代碼如下

    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 聲明:public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
        // 檢測用戶是否指定了messageSource
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // 使當前messageSource能夠使用父容器中的messageSource
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // 用戶沒有指定messageSource
            // 使用一個空的MessageSource,以能夠接受getMessage方法的調用
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                        "': using default [" + this.messageSource + "]");
            }
        }
    }

注意:如果要使用國際化消息,必須提供bean名稱爲messageSource的MessageSource對象,形如下面的配置。

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>/WEB-INF/languages/globe/messages</value>
            </list>
        </property>
        <property name="cacheSeconds" value="1800"/>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

7. 初始化事件傳播器

refresh()方法完成國際化消息對象初始化後,接着調用AbstractApplicationContext的initApplicationEventMulticaster方法爲容器添加事件傳播器,代碼如下。

    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 聲明:public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
        // 檢測用戶是否制定了事件傳播器
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            // 使用默認的事件傳播器
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                        "': using default [" + this.applicationEventMulticaster + "]");
            }
        }
    }

8. 其他初始化

refresh()方法完成國際化消息和事件傳播器的初始化後,把容器的初始化交給onRefresh()方法,代碼如下。

    protected void onRefresh() throws BeansException {
        // For subclasses: do nothing by default.
    }

onRefresh()方法被設計成容器初始化的鉤子,以方便子類初始化其他特定的bean。例如,下面是在AbstractRefreshableWebApplicationContext類中onRefresh()方法被重寫的代碼。

    /**
     * Initialize the theme capability.
     */
    @Override
    protected void onRefresh() {
        this.themeSource = UiApplicationContextUtils.initThemeSource(this);
    }

其中,UiApplicationContextUtils工具類的initThemeSource(ApplicationContext context)方法的代碼如下。

    public static ThemeSource initThemeSource(ApplicationContext context) {
        // 聲明有:public static final String THEME_SOURCE_BEAN_NAME = "themeSource";
        if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
            ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
            // 使themeSource關聯父容器,這個父容器必須實現了ThemeSource接口
            if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
                HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
                if (hts.getParentThemeSource() == null) {

                    hts.setParentThemeSource((ThemeSource) context.getParent());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using ThemeSource [" + themeSource + "]");
            }
            return themeSource;
        }
        else {
            HierarchicalThemeSource themeSource = null;
            if (context.getParent() instanceof ThemeSource) {
                // 把對ThemeSource的操作代理給父容器
                themeSource = new DelegatingThemeSource();
                themeSource.setParentThemeSource((ThemeSource) context.getParent());
            } else {
                // 使用默認的ThemeSource
                themeSource = new ResourceBundleThemeSource();
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
                        "': using default [" + themeSource + "]");
            }
            return themeSource;
        }
    }

9. 註冊監聽器

執行完成子類實現的onRefresh()方法,需要向容器中註冊各種監聽器,此時執行AbstractApplicationContext的registerListeners()方法,這個方法的代碼如下。

    protected void registerListeners() {
        // 首先註冊容器中特定的事件監聽器
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        // 找到用戶配置的所有的監聽器bean名稱
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            // 在事件傳播器中只保存監聽器的bean名稱
            // 這裏不實例化監聽器的原因是爲了讓後處理器在它們真正實例化的時候作用於它們
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        // 發佈那些需要提前發佈的事件
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

10. 實例化非延遲單例bean

前面所有的初始化操作都完成了後,則開始實例化剩下的單例非延遲加載的bean。通過執行AbstractApplicationContext的finishBeanFactoryInitialization方法完成,這個方法的代碼如下。

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 初始化ConversionService
        // 在ConfigurableApplicationContext接口中聲明:String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // 註冊一個默認的內部value解析器
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
                @Override
                public String resolveStringValue(String strVal) {
                    return getEnvironment().resolvePlaceholders(strVal);
                }
            });
        }

        // 初始化LoadTimeWeaverAware對象來支持註冊他們的transformers
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // 停止使用臨時類加載器來做類型匹配
        beanFactory.setTempClassLoader(null);

        // 允許緩存所有的bean元數據定義,不希望今後再更改
        beanFactory.freezeConfiguration();

        // 初始化所有非延遲單例bean
        beanFactory.preInstantiateSingletons();
    }

11. 完成刷新

refresh()方法的最後一步,AbstractApplicationContext的finishRefresh方法,完成容器刷新,執行LifecycleProcessor對象的onRefresh方法,以及發佈刷新事件。代碼如下,

    protected void finishRefresh() {
        // 初始化生命週期處理器,默認爲DefaultLifecycleProcessor 
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        // 首先把刷新操作傳遞給生命週期處理器
        getLifecycleProcessor().onRefresh();

        // 最後發佈容器刷新事件
        publishEvent(new ContextRefreshedEvent(this));

        // 把spring容器加入到LiveBeansView的MBeanServer中
        LiveBeansView.registerApplicationContext(this);
    }
    /**
    * 初始化生命週期處理器
    **/
    protected void initLifecycleProcessor() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 聲明:public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
        if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
            // 使用用戶指定的生命週期處理器
            this.lifecycleProcessor =
                    beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
            if (logger.isDebugEnabled()) {
                logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
            }
        }
        else {
            // 使用默認的聲明週期處理器
            DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
            defaultProcessor.setBeanFactory(beanFactory);
            this.lifecycleProcessor = defaultProcessor;
            beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate LifecycleProcessor with name '" +
                        LIFECYCLE_PROCESSOR_BEAN_NAME +
                        "': using default [" + this.lifecycleProcessor + "]");
            }
        }
    }

到這裏spring的刷新也就完成了。

總結


(1)spring的所有容器都直接或間接繼承了抽象類AbstractApplicationContext。

(2) spring的容器在創建並完成基本的配置後,在初次使用前,還必須執行refresh()方法。

(3)實現BeanDefinitionRegistryPostProcessor 接口的後處理器可以在bean工廠創建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類,它主要把被@Configuration註解的類中定義的bean信息轉換成BeanDefinition對象,並註冊到bean工廠中。

(4)可以自定義BeanPostProcessor工廠後處理器對BeanDefinition對象做處理,比如spring的PreferencesPlaceholderConfigurer工廠後處理器,它把屬性文件中的值與BeanDefinition中相應的屬性值相替換。

(5)指定國際化消息時,MessageSource對象的bean名稱必須爲messageSource。

(6)容器刷新過程中的鉤子方法有:
a. initPropertySources()由子類根據自身的應用環境初始化property資源。
b. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)用於在bean工廠後處理器執行前由子類對bean工廠做更多的初始化操作。
c. onRefresh()用於初始化子類中特定的bean。

(7)LiveBeansView的使用

Spring容器初始化過程中的最後一步,把spring容器加入到LiveBeansView的MBeanServer中。這個LiveBeansView它是一個MBean對象,它的作用是查看當前活動的bean以及這些bean的依賴。下面步驟介紹如何使用它。

a. 在web.xml文件配置如下,其中param-value可以任意取

    <context-param>
        <param-name>spring.liveBeansView.mbeanDomain</param-name>
        <param-value>chyohn_liveBeansView</param-value>
    </context-param>

b. 啓動應用後,打開%JAVA_HOME%/bin/jconsole.exe程序,如下

這裏寫圖片描述

c. 我使用的tomcat服務器啓動的,點擊第2個鏈接,進入的頁面,如下

這裏寫圖片描述

上面的JSON數據中就包含當前spring容器中所有的bean,是不是很神奇?這也是java MBean的一個例子。

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