建立ApplicationContext與BeanFactory時的區別-Spring源碼學習之容器的基本實現

傳送門spring

能夠加載XML兩種方法

使用 BeanFactory 加載 XML

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));

Ps:由於我是跟着《Spring源碼深度解析》學習的,而這本書出版在13年9月,這一種方法在新的Spring版本中已經廢棄掉了,取而代之的是下面的方法;但既然學了,那就仍是記錄一下,學習一下開發者的思想也是不錯的.數組

使用 ApplicationContext 加載 XML

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

相同點

上述二者都是經過加載XMl配置文件的方式加載Bean,然後者是前者的擴展,提供了更多的功能,即ApplicationContext擁有BeanFactory的所有功能,在絕大多數的"典型的"企業應用和系統,ApplicationContext都優先於BeanFactory.app

不一樣點

BeanFactory是延遲加載,若是一個Bean當中存在屬性沒有加載,會在第一次調用getBean()方法的時候報錯,而ApplicationContext會在讀取Xml文件後,若是配置文件沒有錯誤,就會將全部的Bean加載到內存中,缺點就是在Bean較多的時候比較佔內存,程序啓動較慢.函數

Spring容器加載中最重要的兩個類

DefaultListableBeanFactory

XmlBeanFactory繼承自DefaultListableBeanFactory,然後者是整個Bean加載的核心部分,是Spring註冊及加載Bean的默認實現,而XmlBeanFactory使用了自定義的Xml讀取器XmlBeanDefinitionReader,實現了個性化的BeanDefinitionReader讀取.學習

XmlBeanDefinitionReader

主要負責Xml文件的讀取、解析和註冊功能this


加載時的區別

上面的兩種方法的處理大體相同,讓咱們經過時序圖看看二者在加載時的區別:code

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));

粗略時序圖:xml

image
首先,將applicationContext.xmlClassPathResource進行封裝獲得Resource資源,Resource接口將全部的資源文件統一處理,當經過Resource相關類完成了對配置文件的封裝以後,就由XmlBeanDefinitionReader進行讀取和解析.對象

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

粗略時序圖:繼承

image
附上ClassPathXmlApplicatioContext構造函數的源碼:

public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
            throws BeansException {

        super(parent);
        Assert.notNull(paths, "Path array must not be null");
        Assert.notNull(clazz, "Class argument must not be null");
        this.configResources = new Resource[paths.length];  //建立資源數組  private Resource[] configResources;
        for (int i = 0; i < paths.length; i++) {
            this.configResources[i] = new ClassPathResource(paths[i], clazz);
        }
        refresh();  //解析工做,ClassPathXmlApplicatioContext繼承來自AbstractApplicationContext中的方法
    }

首先,一樣是封裝配置文件,但封裝完成以後並無直接進行讀取,而是調用了refresh()方法(這個方法裏面進行了不少操做,擴展的功能幾乎是在這裏面實現的),refresh()方法中的obtainFreshBeanFactory()方法負責初始化BeanFactory,並對XMl文件讀取,讀取的核心實現是該方法中調用的refreshBeanFactory()方法,這個方法再調用圖中的loadBeanDefinitions(beanFactory)方法(因爲板面緣由,沒有畫出),而後在其中建立XmlBeanDefinitionReader對象,再將最初封裝的資源文件數組進行依次讀取並解析.

兩者在後面的Xml解析工做都幾乎是同樣的,都採用了SAX解析,區別就在於解析以前的準備和解析以後的完善工做.

相關文章
相關標籤/搜索