可以加載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.
不同點
BeanFactory是延遲加載,如果一個Bean當中存在屬性沒有加載,會在第一次調用getBean()方法的時候報錯,而ApplicationContext會在讀取Xml文件后,如果配置文件沒有錯誤,就會將所有的Bean加載到內存中,缺點就是在Bean較多的時候比較占內存,程序啟動較慢.
Spring容器加載中最重要的兩個類
DefaultListableBeanFactory
XmlBeanFactory繼承自DefaultListableBeanFactory,而后者是整個Bean加載的核心部分,是Spring注冊及加載Bean的默認實現,而XmlBeanFactory使用了自定義的Xml讀取器XmlBeanDefinitionReader,實現了個性化的BeanDefinitionReader讀取.
XmlBeanDefinitionReader
主要負責Xml文件的讀取、解析和注冊功能
加載時的區別
上面的兩種方法的處理大致相同,讓我們通過時序圖看看兩者在加載時的區別:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));
粗略時序圖:

首先,將applicationContext.xml用ClassPathResource進行封裝得到Resource資源,Resource接口將所有的資源文件統一處理,當通過Resource相關類完成了對配置文件的封裝之后,就由XmlBeanDefinitionReader進行讀取和解析.
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
粗略時序圖:

附上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解析,區別就在於解析之前的准備和解析之后的完善工作.
