擴充spring元件之自定義標籤

稀飯下雪發表於2019-04-14

乾貨點

瞭解如何基於spring自定義標籤,這是自定義元件的第一步。而最重要的是瞭解了這個過程後也可以大致瞭解spring自身部分元件是怎麼相互工作和觸發的,如spring-aop,元件可以通過反調AopNamespaceHandler瞭解大致面貌。

系列文描述

書寫該系列文的初衷是因為最近正在負責一個元件的開發,於是打算將接觸和學習到的知識寫進部落格裡。這第一篇,記錄基於spring如何自定義標籤。

自定義標籤的作用

自定義標籤可以說是spring為了給類似你我這樣的開發人員擴充套件元件使用的,因為它提供了一個標準的公共可插拔的介面;目前我們都知道spring非常強大,不過實際上除了spring-core和spring-beans外,其他都是通過自定義標籤擴充套件實現的,其次還有一些開源元件也是,如dubbo等。所以,對於想擴充套件spring元件的小夥伴來說,瞭解如何自定義標籤和相應的原理是必須走的第一步。

那麼如何自定義標籤

自定義標籤可以簡單分為四個步驟,分別是

  • 編寫.schemas檔案,通知spring容器我們定義的xsd檔案在哪裡;
  • 編寫.xsd檔案,定義配置時可以使用的屬性限制或者說支援的那些屬性配置;
  • 編寫.handlers 檔案,擴充套件NamespaceHandler名稱空間註冊器和定義及誒喜慶;
  • 在xml檔案中使用自定義標籤

下面我將以目前開發元件中的程式碼做例子,從在xml檔案中使用開始一步一步逆推,覆盤整個自定義標籤的過程。

首先,先看下目錄情況

resource元件.png

common是我自定義的一個元件組,其中包含的resource元件便是這次使用了自定義標籤的主體,可以從截圖中看出部分相關檔案的存放位置。

test-demo.png

test-demo是為了測試這次元件中的自定義標籤是否有作用而存在,test-demo只是匯入了common元件組而已,再從中呼叫resource元件。好了,目錄結構描述完了,接下來進入正題。

看下xml檔案如何使用自定義標籤

applicationContext.xml.png

在第4行這裡引入了resource對應的名稱空間,spring會從本地掃.handlers,從中找到對應的Key值和Value值,如

spring.handlers.png

spring容器會將Key值對應的具體名稱空間註冊註冊入容器,至於這個空間註冊器是怎麼樣的,後面再表,繼續描述xml檔案。 在之後,我們可以在xmlns:schemaLocation中找到類似的Key&Value的配置,這次的配置是告訴spring容器從哪裡查詢XSD檔案,這點可以從第六行找到,對應的XSD檔案地址是: www.nuofankj.com/resource/re… 細心的話不難發現,這是一個網路地址,是的,確實如此,不過spring的容器卻是先在本地掃.schemas檔案,並且讀取其中的鍵值對關係,從中找到本地的檔案地址,如果找不到,才會從網路中讀取。如spring.schemas檔案:

spring.schemas.png

該檔案以一種鍵值對的形式表明了檔案在本地的地址,那就是resource.xsd,之後spring容器便會找到resource.xsd檔案做校驗。如

resource.xsd.png
resource.xsd.png

眾所周知,XSD檔案的作用是定義配置時可以使用的屬性限制或者說支援那些屬性配置。我們可以直接看applicationContext.xml中的配置

applicationContext.xml.png

走到這一步就說明配置檔案配置好了,接下來便是如何解析的問題了。也就是上文提到com.nuofankj.resource.schema.NamespaceHandler

那麼NamespaceHandler類是什麼樣的

NamespaceHandler.java.png

該類擴充套件自NamespaceHandlerSupport,目的是將元件註冊到Spring容器中。其中以SchemaNames.CONFIG_ELEMENT為名註冊了一個類ConfigDefinitionParserSchemaNames.CONFIG_ELEMENT對應的變數就是config字串,目的就是為了解析

config.png

顯然,ConfigDefinitionParser就是作為解析器存在的。

接下來看看該解析器是什麼樣的

ConfigDefinitionParser.png

該解析器繼承了AbstractBeanDefinitionParser類,並且重寫parseInternal方法,其中的引數element攜帶resource:config中的所有配置,我們可以將自身的解析業務放在該函式中。以我自定義的元件為例:

AbstractBeanDefinitionParser.png

我這邊的業務是將SchemaNames.PACKAGE_ELEMENT包下的所有類掃出來並且放入list中儲存,已經讀取出type、suffix等相關配置。

到這一步,自定義標籤的過程就全部理清楚了。 相關原始碼地址:github.com/wiatingpub/…


系列部落格可以關注公眾號:

公眾號.jpg

個人網站:myblog.lixifan.cn/

相關文章