創建ApplicationContext與BeanFactory時的區別-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.

不同點

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"));

粗略時序圖:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM