Spring源碼閱讀——ClassPathXmlApplicationContext(一)

ClassPathXmlApplicationContext的繼承關係

ClassPathXmlApplicationContext繼承了AbstractXmlApplicationContext,實現了ApplicationContext接口。BeanFactory是全部容器的頂級接口,spring中全部容器都是基於BeanFactory的。ClassPathXmlApplicationContext繼承關係以下圖:
clipboard.pngspring

建立ClassPathXmlApplicationContext實例

ClassPathXmlApplicationContext中有多個構造方法,最終都經過以下的構造方法初始化容器:post

public ClassPathXmlApplicationContext(
          String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
          throws BeansException {
     super(parent);
     setConfigLocations(configLocations);
     if (refresh) {
          refresh();
     }
}

其中,refresh()方法完成了容器的初始化。this

refresh()方法的實現分析

refresh()方法的實現代碼以下spa

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 上下文刷新的準備工做,完成一下工做:
            //一、設置啓動時間、是否關閉和是否激活
            //二、在上下文中初始化任何佔位符屬性資源
            //三、驗證標記爲必需的屬性文件是可解析的
            prepareRefresh();

            // 建立DefaultListableBeanFactory實例,解析xml配置文件,註冊bean
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            //對BeanFactory進行各類功能填充
            //在此方法中,增長的支持@Qualifier與@Autowired這兩個註解
            prepareBeanFactory(beanFactory);

            try {
                // 由子類實現,可進行自定義擴展
                postProcessBeanFactory(beanFactory);

                // 激活BeanFactory的處理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // 初始化message資源
                initMessageSource();

                // 爲這個context初始化一個事件廣播器
                initApplicationEventMulticaster();

                // 由子類實現,初始化其餘bean
                onRefresh();

                // 註冊已實現ApplicationListener接口的Bean
                registerListeners();

                // 實例化全部非延遲初始化的單例模式bean
                finishBeanFactoryInitialization(beanFactory);

                // 完成刷新過程,通知生命週期處理器lifecycleProcessor刷新過程,同時發出ContextRefreshEvent通知監聽者
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

obtainFreshBeanFactory()方法的實現

此方法主要做用是建立DefaultListableBeanFactory實例,解析xml配置文件,註冊bean。內部調用了調用了AbstractRefreshableApplicationContext類的refreshBeanFactory()方法建立bean工廠。refreshBeanFactory()方法實現以下:code

protected final void refreshBeanFactory() throws BeansException {
        //若是beanfactory存在,銷燬因此bean和關閉beanfactory
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //定義beanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            //將bean解析爲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);
        }
    }

refreshBeanFactory()方法中,首先判斷是否存在beanfactory,若是存在,銷燬全部Bean,關閉beanfactory。createBeanFactory()方法建立一個新的容器。在本方法中,最重要的是loadBeanDefinitions(beanFactory),調用這個方法解析xml配置文件,註冊bean。xml

loadBeanDefinitions(beanFactory)方法的實現以下

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 根據給定的BeanFactory建立一個新的 XmlBeanDefinitionReader
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // 根據上下文配置bean definition reader
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        initBeanDefinitionReader(beanDefinitionReader);
        //經過beanDefinitionReader解析xml配置文件,註冊bean
        loadBeanDefinitions(beanDefinitionReader);
    }

在XmlBeanDefinitionReader中實現了loadBeanDefinitions(beanDefinitionReader)方法,代碼以下:blog

//省略了異常處理相關代碼,主要邏輯以下
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        //從encodedResource中獲得InputSource和Resource
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        InputStream inputStream = encodedResource.getResource().getInputStream();
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
         //調用此方法加載BeanDefinition
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }

doLoadBeanDefinitions(inputSource, encodedResource.getResource())中,從資源文件中讀取Document,而且調用registerBeanDefinitions(doc, resource)註冊BeanDefinition,省略無關代碼,實現以下:繼承

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            //從resource中讀取獲得Document
            Document doc = doLoadDocument(inputSource, resource);
            //註冊BeanDefinition
            return registerBeanDefinitions(doc, resource);
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
}

在registerBeanDefinitions(doc, resource)方法中,BeanDefinition的註冊時委託給BeanDefinitionDocumentReader的registerBeanDefinitions(doc, createReaderContext(resource))方法進行註冊的。接口

相關文章
相關標籤/搜索