spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)

前言

一直據說spring對java進行了重定義,設計和封裝體系比較宏大;加上最近遇到了spring的問題,爲了更好地定位問題,最近一段啃了一下spring源碼。我用的源碼版本是5.2.28,下面就把最近的研究成果作一下分享。java

個人源碼閱讀目標主要是IOC和AOP這兩塊,先來看看spring容器加載這塊
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
咱們重點來分析一下前兩種容器加載方式。至於嵌入式容器加載方式,後續接觸到SpringBoot時再介紹。
雖然如今spring boot大行其道,但就底層的實現來說不少都是基於springframework來實現的。因此咱們由必要分析一下經過xml方式加載容器方式。註解方式容器加載方式做爲當前主流一樣也是分析的重點(其實它們在執行流程上有不少相同的處理環節)。
先來總體看看這兩種方式的容器加載流程spring

容器加載流程

spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
注:流程中標記的環節是接下來要陸續分析的重點
從以上兩種方式容器加載的流程咱們能夠看到,從總體上講,xml配置解析方式只比註解掃描方式多了一個xml解析的環節,解析的結果最終仍是要封裝和註冊beandefinition對象。另外註解掃描方式會把三大組件的註冊、包的掃描環節提早完成。OK, 接下來咱們一個一個來看。數據結構

xml配置解析

容器入口
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
容器上下文刷新refresh()入口
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
AbstractRefreshableApplicationContext.refreshBeanFactory()模板方法
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
AbstractXmlApplicationContext.loadBeanDefinitions()解析配置核心方法
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
將配置資源封裝成InputStream流對象
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
BeanDefinitionDocumentReader.registerBeanDefinitions()解析和註冊beandefinition入口方法
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()核心解析方法
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
DefaultBeanDefinitionDocumentReader.parseDefaultElement()默認標籤解析過程
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
解析中間結果包裝BeanDefinitionHolder包裝對象
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
BeanDefinitionParserDelegate.parseBeanDefinitionElement()解析bean標籤的各類屬性和子元素
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
通用beandefinition數據結構
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()裝飾beandefinition其它功能
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
這種裝飾器模式在自定義標籤解析有使用
BeanDefinitionReaderUtils.registerBeanDefinition()註冊beandefinition工具類方法
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
BeanDefinition註冊的目標接口BeanFactory--->DefaultListableBeanFactory對象
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
BeanDefinitionParserDelegate.parseCustomElement()解析自定義標籤
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
以上的handlers的解析對於spring來源說有不少,咱們也能夠自定義標籤對象,之內置的context標籤爲例,包含如下部分
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ComponentScanBeanDefinitionParser.parse()解析<context:component-scan/>標籤解析過程
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
建立ClassPathBeanDefinitionScanner掃描器
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ClassPathScanningCandidateComponentProvider.registerDefaultFilters()註冊默認的註解類型過濾器
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ClassPathBeanDefinitionScanner.doScan()包class文件掃描
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ClassPathScanningCandidateComponentProvider.findCandidateComponents()查找符合條件class的過程
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ComponentScanBeanDefinitionParser.registerComponents()註冊核心三大組件
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)ide

註解掃描

AnnotationConfigApplicationContext構造函數註解掃描入口
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
AnnotationConfigUtils.registerAnnotationConfigProcessors()註冊三大組件,過程同xml解析中組件註冊相同
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ClassPathBeanDefinitionScanner掃描器註冊和NamespaceUri處理器
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
ClassPathBeanDefinitionScanner.scan()執行包掃描
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
AbstractApplicationContext.refresh()容器上下文刷新, 同xml配置解析加載相似
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
註解掃描重寫GenericApplicationContext.refreshBeanFactory()方法(沒有重要實現);xml配置解析重寫的是:AbstractRefreshableApplicationContext.refreshBeanFactory()方法(核心實現就在此);
refresh()容器刷新的後續步驟,兩種以上兩種容器加載方式都相同,這裏就再也不贅述 。函數

調用時序

最後,讓咱們來梳理一下xml配置解析和註解掃描兩種方式的beandefinition封裝和註解過程
xml配置解析和註冊beandefinition調用時序
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)
註解掃描和註冊beandefinition調用時序
spring源碼解析 - spring容器加載源碼(beandefinition封裝和註冊過程)工具

總結

至此兩種容器加載方式的beandefinition封裝和註冊過程就介紹完畢了,有任何關於這塊的問題歡迎在下方留言!下次咱們重點解析bean實例化過程。更多spring源碼乾貨請繼續關注!ui

相關文章
相關標籤/搜索