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