深刻理解Spring系列之四:BeanDefinition裝載前奏曲

框架的源碼分析,有些代碼能夠暫時忽略,如Spring如何進行XML模式校驗的、XML解析的細節等,這些代碼能夠在瞭解了總體的原理以後,再作針對性的分析,關注重點內容便可,切記在一開始就去深挖每一個細節,這樣不只會耗費很長時間,並且容易陷入某個坑裏出不來。bash

《深刻理解Spring系列之一:開篇》示例中的ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationgContext.xml")爲入口,進入源碼內部,ClassPathXmlApplicationContext類圖以下。
app



ClassPathXmlApplicationContext有多個構造方法,跟蹤代碼能夠發現,最終使用的是下面這個方法,框架

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
      refresh();
    }
  }複製代碼

方法的參數很容易理解,configLocations指Spring的xml配置文件;refresh指是否須要刷新,這個refresh決定了是否進行bean解析、註冊及實例化;parent指父ApplicationContext。setConfigLocations方法就是設置框架要加載的資源文件的位置。進入refresh方法,這個方法繼承自AbstractApplicationContext,因此具體實如今AbstractApplicationContext類中,具體代碼以下。源碼分析

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
      //容器預先準備,記錄容器啓動時間和標記
      prepareRefresh();
      //建立bean工廠,裏面實現了BeanDefinition的裝載
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      //配置bean工廠的上下文信息,如類裝載器等
      prepareBeanFactory(beanFactory);
      try {
        //在BeanDefinition被裝載後,提供一個修改BeanFactory的入口
        postProcessBeanFactory(beanFactory);
        //在bean初始化以前,提供對BeanDefinition修改入口,PropertyPlaceholderConfigurer在這裏被調用
        invokeBeanFactoryPostProcessors(beanFactory);
        //註冊各類BeanPostProcessors,用於在bean被初始化時進行攔截,進行額外初始化操做
        registerBeanPostProcessors(beanFactory);
        //初始化MessageSource
        initMessageSource();
        //初始化上下文事件廣播
        initApplicationEventMulticaster();
        //模板方法
        onRefresh();
        //註冊監聽器
        registerListeners();
        //初始化全部未初始化的非懶加載的單例Bean
finishBeanFactoryInitialization(beanFactory);
        //發佈事件通知
        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(); } } }複製代碼

這個方法裏面就是IOC容器初始化的大體步驟了。上面步驟的第二步完成了BeanDefinition的裝載,進入obtainFreshBeanFactory方法,這個方法的具體實現也在AbstractApplicationContext類中,代碼以下所示。post

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}複製代碼

這裏面主要關注refreshBeanFactory方法,這個方法在AbstractApplicationContext類中並未實現,具體實如今子類AbstractRefreshableApplicationContext中,代碼以下。ui

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
      destroyBeans();
closeBeanFactory();
    }
    try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
        this.beanFactory = beanFactory;
      }
    }
    catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}複製代碼

這個方法使用了final修飾,也就是不能被重寫了。首先檢查BeanFactory是否已經存在,若是存在則銷燬並關閉,而後新建一個BeanFactory,其實就是一個DefaultListableBeanFactory,這個DefaultListableBeanFactory就是《深刻理解Spring系列之一:開篇》說的那個。而後進行BeanFactory的屬性設置,設置是否容許重寫BeanDefinition、是否容許循環引用,接着loadBeanDefinitions方法就是BeanDefinition載入的入口了,這個方法在AbstractRefreshableApplicationContext本類中並未實現,具體在其子類中實現,根據用途不一樣有多個實現子類,下一篇內容將分析基於最基本的解析xml方式的AbstractXmlApplicationContext類中的實現。this

相關文章
相關標籤/搜索