本文轉自五月的倉頡 https://www.cnblogs.com/xrq730
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裏查看
喜歡的話麻煩點下Star哈
文章將同步到我的個人博客:
www.how2playlife.com
本文是微信公衆號【Java技術江湖】的《Spring和SpringMVC源碼分析》其中一篇,本文部分內容來源於網絡,爲了把本文主題講得清晰透徹,也整合了很多我認爲不錯的技術博客內容,引用其中了一些比較好的博客文章,如有侵權,請聯繫作者。
該系列博文會告訴你如何從spring基礎入手,一步步地學習spring基礎和springmvc的框架知識,並上手進行項目實戰,spring框架是每一個Java工程師必須要學習和理解的知識點,進一步來說,你還需要掌握spring甚至是springmvc的源碼以及實現原理,才能更完整地瞭解整個spring技術體系,形成自己的知識框架。
後續還會有springboot和springcloud的技術專題,陸續爲大家帶來,敬請期待。
爲了更好地總結和檢驗你的學習成果,本系列文章也會提供部分知識點對應的面試題以及參考答案。
如果對本系列文章有什麼建議,或者是有什麼疑問的話,也可以關注公衆號【Java技術江湖】聯繫作者,歡迎你參與本系列博文的創作和修訂。
<!-- more -->
前言
xml的讀取應該是Spring的重要功能,因爲Spring的大部分功能都是以配置做爲切入點的。
我們在靜態代碼塊中讀取配置文件可以這樣做:
//這樣來加載配置文件
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
(1)XmlBeanFactory 繼承 AbstractBeanDefinitionReader ,使用ResourceLoader 將資源文件路徑轉換爲對應的Resource文件。
(2)通過DocumentLoader 對 Resource 文件進行轉換,將 Resource 文件轉換爲 Document 文件。
(3)通過實現接口 BeanDefinitionDocumentReader 的 DefaultBeanDefinitionDocumentReader 類對Document 進行解析,並且使用 BeanDefinitionParserDelegate對Element進行解析。
step1:
在平常開發中,我們也可以使用Resource 獲取 資源文件:
Resource resource = new ClassPathResource("application.xml");
InputStream in = resource.getInputStream();
step2:
在資源實現加載之前,調用了 super(parentBeanFactory) -- /*Ignore the given dependency interface for autowiring.(忽略接口的自動裝配功能)/
調用XmlBeanDefinitionReader 的 loadBeanDefinitions()方法進行加載資源:
(1) 對Resource資源進行編碼
(2) 通過SAX讀取XML文件來創建InputSource對象
(3) 核心處理
可以很直觀的看出來是這個function是在解析xml文件從而獲得對應的Document對象。
在doLoadDocument方法裏面還存一個方法getValidationModeForResource()用來讀取xml的驗證模式。(和我關心的沒什麼關係,暫時不看了~)
轉換成document也是最常用的方法:
step3 : 我們已經step by step 的看到了如何將xml文件轉換成Document的,現在就要分析是如何提取和註冊bean的。
/*Register the bean definitions contained in the given DOM document/
參數doc是doLoadBeanDefinitions()方法傳進來的 loadDocument 加載過來的。這邊就很好的體現出了面向對象的單一全責原則,將邏輯處理委託給單一的類去處理。
在這邊單一邏輯處理類是: BeanDefinitionDocumentReader
核心方法: <font color="#FF0000">documentReader.registerBeanDefinitions(doc, createReaderContext(resource));</font>
<font color="#FF0000"></font>
<font color="#FF0000">開始解析:</font>
<font color="#FF0000"></font>
在Spring的xml配置中有兩種方式來聲明bean:
一種是默認的: <bean id = " " class = " " />
還有一種是自定義的: < tx : annotation-driven / >
通過xml配置文件的默認配置空間來判斷:http://www.springframework.org/schema/beans
對於默認標籤的解析:
對Bean 配置的解析:
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 返回BeanDefinitionHolder
這邊代碼大致看下來:
- 提取元素中的id和name屬性
- 進一步解析將其他屬性封裝到 BeanDefinition 的實現類中
- 如果沒有指定beanName 變使用默認規則生成beanName
- 封裝類BeanDefinitionHolder
可以先了解一下 BeanDefinition 這個類的作用。
BeanDefinition是一個接口,對應着配置文件中<bean>裏面的所有配置,在Spring中存在着三個實現類:
在配置文件中,可以定義父<bean>和子<bean>,父<bean>是用RootDefinition來表示,子<bean>是用ChildBeanDefinition來表示。
Spring 通過BeanDefiniton將配置文件中的<bean>配置信息轉換爲容器內部表示,並且將這些BeanDefinition註冊到BeanDefinitonRegistry中。
Spring容器的BeanDefinitonRegistry就像是Spring配置信息的內存數據庫,主要是以map的形式保存的。
因此解析屬性首先要創建用於承載屬性的實例:
然後就是各種對屬性的解析的具體方法: