Spring IOC 源碼解析(二),容器中的 BeanDefinition(Annotation 解析篇)

前言

Spring 源碼解析篇都沒有貼源碼,貼了就太多太長了研究源碼時候可能容易看暈,先大致理清楚源碼設計編寫的總體流程,流程中的幾個階段,而後在細看每個階段,固然這每個階段裏面可能又是涉及到龐大的代碼量,那麼又須要將其分爲多個階段,這樣一層一層的抽絲剝繭去看不會讓本身一上來就產生強烈的挫敗感(由於直接去 DEBUG Spring 源碼會發現太深了)數組

經過掃描包路徑加載其下的 Class 文件爲 Resource 數組

  1. 首先是調用構造器建立 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 他們分別是用於處理讀取註解 BeanDefinition 和 classPath 路徑下的 BeanDefinition 的ide

  2. 調用 ClassPathBeanDefinitionScanner 的 doScan 方法開始作掃描工做設計

  3. 在 ClassPathScanningCandidateComponentProvider 根據須要掃描的路徑調用 GenericApplicationContext 的 getResources 方法,該方法會去遞歸掃描包路徑下面全部的 Class 文件而後將其解析爲 Resource 數組返回;就算一個類沒有被 @Component 等註解修飾也會加載到 Resource 數組中3d

根據 Resource 數組建立 BeanDefinition 並放入容器中

  1. 首先建立 MetadataReader 用於讀取 Resource 文件的元數據,主要包括 Resource、 ClassMetadata、AnnotationMetadatacdn

  2. 而後判斷是否在類上標註了 @Component 等註解,若是標註了進行下一步, 若是隻是一個單純的類則跳過對象

  3. 根據 MetadataReader 等信息建立 ScannedGenericBeanDefinition 放入 Set 中,ScannedGenericBeanDefinition 是一個早期 的 BeanDefinition 它目前包含了,類的元數據,Resource 文件,ClassName 等信息,Spring 稱 之爲 candidates(候選者)blog

  4. 遍歷這些 candidates,根據其包含的信息作下一步操做;主要包含提取出 Scope 信息,建立 BeanName(通常是將相似 com.xxx.User 全稱取類名稱小寫 beanName = user)遞歸

  5. 而後根據上面獲取到的信息去建立一個 BeanDefinitionHolder ,該對象除了持有 BeanDefinition 外存有 beanName 和別名的相關信息get

  6. 最後根據 BeanDefinitionHolder 獲取到 BeanDefinition 放入到 DefaultListableBeanFactory 的 beanDefinitionMap 中,同時將其 beanName 對應的別名存放在 Map 中源碼

總結

關於掃描包加載註解類的步驟爲,首先根據定義路徑遞歸遍歷其下全部文件將其解析爲 Resource 數組。而後遍歷 Resource 數組根據其信息建立 ScannedGenericBeanDefinition 這樣一個待完善的 BeanDefinition 集合。而後遍歷這個集合解析出 Scope、建立 BeanName 解析出別名等信息據此建立出 BeanDefinition。最後將 BeanDefinition 放入容器中同時保存好它的對應別名信息

相關文章
相關標籤/搜索