一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring中XML schema擴展機制的深入講解

Spring中XML schema擴展機制的深入講解

2021-05-29 15:07徐靖峰 Java教程

這篇文章主要給大家介紹了關于Spring中XML schema擴展機制的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

很久沒有寫關于 spring 的文章了,最近在系統梳理 dubbo 代碼的過程中發現了 xml schema 這個被遺漏的知識點。由于工作中使用 springboot 比較多的原因,幾乎很少接觸 xml,此文可以算做是亡羊補牢,另一方面,也為后續的 dubbo 源碼解析做個鋪墊。

xml schema 擴展機制是啥?從spring2.0開始,spring提供了xml schema可擴展機制,用戶可以自定義xml schema文件,并自定義xml bean解析器,并集成到spring ioc 容器中。這并不是一塊很大的知識點,翻閱一下 spring 的文檔,我甚至沒找到一個貫穿上下文的詞來描述這個功能,xml schema authoring 是文檔中對應的標題,簡單來說:

spring 為基于 xml 構建的應用提供了一種擴展機制,用于定義和配置 bean。 它允許使用者編寫自定義的 xml bean 解析器,并將解析器本身以及最終定義的 bean 集成到 spring ioc 容器中。

Spring中XML schema擴展機制的深入講解

dubbo 依賴了 spring,并提供了一套自定義的 xml 標簽,<dubbo:application> ,<dubbo:registry> ,<dubbo:protocol>,<dubbo:service>。作為使用者,大多數人只需要關心這些參數如何配置,但不知道有沒有人好奇過,它們是如何加載進入 spring 的 ioc 容器中被其他組件使用的呢?這便牽扯出了今天的主題:spring 對 xml schema 的擴展支持。

自定義 xml 擴展

為了搞懂 spring 的 xml 擴展機制,最直接的方式便是實現一個自定義的擴展。實現的步驟也非常簡單,分為四步:

Spring中XML schema擴展機制的深入講解

  • 編寫一個 xml schema 文件描述的你節點元素。
  • 編寫一個 namespacehandler 的實現類
  • 編寫一個或者多個 beandefinitionparser 的實現 (關鍵步驟).
  • 注冊上述的 schema 和 handler。

我們的目的便是想要實現一個 kirito xml schema,我們的項目中可以自定義 kirito.xml,在其中會以 kirito 為標簽來定義不同的類,并在最終的測試代碼中驗證這些聲明在 kirito.xml 的類是否被 spring 成功加載。大概像這樣,是不是和 dubbo.xml 的格式很像呢?

Spring中XML schema擴展機制的深入講解

動手實現

有了明確的目標,我們逐步開展自己的工作。

1 編寫kirito.xsd

resources/meta-inf/kirito.xsd

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://www.cnkirito.moe/schema/kirito"
   xmlns:xsd="http://www.w3.org/2001/xmlschema"
   xmlns:beans="http://www.springframework.org/schema/beans"
   targetnamespace="http://www.cnkirito.moe/schema/kirito"> ①
 
 <xsd:import namespace="http://www.springframework.org/schema/beans"/>
 
 <xsd:element name="application"> ②
  <xsd:complextype>
   <xsd:complexcontent>
    <xsd:extension base="beans:identifiedtype">
     <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:extension>
   </xsd:complexcontent>
  </xsd:complextype>
 </xsd:element>
 
 <xsd:element name="service"> ②
  <xsd:complextype>
   <xsd:complexcontent>
    <xsd:extension base="beans:identifiedtype">
     <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:extension>
   </xsd:complexcontent>
  </xsd:complextype>
 </xsd:element>
 
 
</xsd:schema>

① 注意這里的 targetnamespace="http://www.cnkirito.moe/schema/kirito" 這便是之后 kirito 標簽的關鍵點。

② kirito.xsd 定義了兩個元素: application 和 service,出于簡單考慮,都只有一個 name 字段。

schema 的意義在于它可以和 eclipse/idea 這樣智能化的集成開發環境形成很好的搭配,在編輯 xml 的過程中,用戶可以獲得告警和提示。 如果配置得當,可以使用自動完成功能讓用戶在事先定義好的枚舉類型中進行選擇。

2 編寫kiritonamespacehandler

?
1
2
3
4
5
6
7
8
public class kiritonamespacehandler extends namespacehandlersupport {
 
 @override
 public void init() {
  super.registerbeandefinitionparser("application", new kiritobeandefinitionparser(applicationconfig.class));
  super.registerbeandefinitionparser("service", new kiritobeandefinitionparser(servicebean.class));
 }
}

完成 schema 之后,還需要一個 namespacehandler 來幫助 spring 解析 xml 中不同命名空間的各類元素。

?
1
2
3
<kirito:application name="kirito"/>
<dubbo:application name="dubbo"/>
<motan:application name="motan"/>

不同的命名空間需要不同的 namespacehandler 來處理,在今天的示例中,我們使用 kiritonamespacehandler 來解析 kirito 命名空間。kiritonamespacehandler 繼承自 namespacehandlersupport 類,并在其 init() 方法中注冊了兩個 beandefinitionparser ,用于解析 kirito 命名空間/kirito.xsd 約束中定義的兩個元素:application,service。beandefinitionparser 是下一步的主角,我們暫且跳過,將重心放在父類 namespacehandlersupport 之上。

?
1
2
3
4
5
public interface namespacehandler {
 void init();
 beandefinition parse(element element, parsercontext parsercontext);
 beandefinitionholder decorate(node source, beandefinitionholder definition, parsercontext parsercontext);
}

namespacehandlersupport 是 namespacehandler 命名空間處理器的抽象實現,我粗略看了namespacehandler 的幾個實現類,parse 和 decorate 方法可以完成元素節點的組裝并通過 parsercontext 注冊到 ioc 容器中,但實際我們并沒有調用這兩個方法,而是通過 init() 方法注冊 beandefinitionparser 來完成解析節點以及注冊 bean 的工作,所以對于 namespacehandler,我們主要關心 init 中注冊的兩個 beandefinitionparser 即可。

3 編寫kiritobeandefinitionparser

在文章開始我們便標記到 beandefinitionparser 是最為關鍵的一環,每一個 beandefinitionparser 實現類都負責一個映射,將一個 xml 節點解析成 ioc 容器中的一個實體類。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class kiritobeandefinitionparser implements beandefinitionparser {
 
 private final class<?> beanclass;
 
 public kiritobeandefinitionparser(class<?> beanclass) {
  this.beanclass = beanclass;
 }
 
 private static beandefinition parse(element element, parsercontext parsercontext, class<?> beanclass) {
  rootbeandefinition beandefinition = new rootbeandefinition();
  beandefinition.setbeanclass(beanclass);
  beandefinition.setlazyinit(false);
  string name = element.getattribute("name");
  beandefinition.getpropertyvalues().addpropertyvalue("name", name);
  parsercontext.getregistry().registerbeandefinition(name, beandefinition);
  return beandefinition;
 }
 
 @override
 public beandefinition parse(element element, parsercontext parsercontext) {
  return parse(element, parsercontext, beanclass);
 }
}

由于我們的實體類是非常簡單的,所以不存在很復雜的解析代碼,而實際項目中,往往需要大量的解析步驟。parse 方法會解析一個個 xml 中的元素,使用 rootbeandefinition 組裝成對象,并最終通過 parsercontext 注冊到 ioc 容器中。

至此,我們便完成了 xml 文件中定義的對象到 ioc 容器的映射。

4 注冊schema和handler

最后一步還需要通知 spring,告知其自定義 schema 的所在之處以及對應的處理器。

resources/meta-inf/spring.handlers

http\://www.cnkirito.moe/schema/kirito=moe.cnkirito.sample.xsd.kiritonamespacehandler

resources/meta-inf/spring.schemas

http\://www.cnkirito.moe/schema/kirito/kirito.xsd=meta-inf/kirito.xsd

沒有太多可以說的,需要遵守 spring 的約定。

至此一個自定義的 xml schema 便擴展完成了,隨后來驗證一下。

驗證擴展

我們首先定義好 kirito.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
 
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
  xmlns:kirito="http://www.cnkirito.moe/schema/kirito"
  xsi:schemalocation=" http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.cnkirito.moe/schema/kirito
        http://www.cnkirito.moe/schema/kirito/kirito.xsd">
 
 <kirito:application name="kirito-demo-application"/>
 
 <kirito:service name="kirito-demo-service"/>
 
</beans>

使用 spring 去加載它,并驗證 ioc 容器中是否存在注冊成功的 bean。

?
1
2
3
4
5
6
7
8
9
10
11
12
@springbootapplication
@importresource(locations = {"classpath:kirito.xml"})
public class xmlschemaauthoringsampleapplication {
 
 public static void main(string[] args) {
  configurableapplicationcontext applicationcontext = springapplication.run(xmlschemaauthoringsampleapplication.class, args);
  servicebean servicebean = applicationcontext.getbean(servicebean.class);
  system.out.println(servicebean.getname());
  applicationconfig applicationconfig = applicationcontext.getbean(applicationconfig.class);
  system.out.println(applicationconfig.getname());
 }
}

觀察控制臺的輸出:

kirito-demo-service
kirito-demo-application

一個基礎的基于 xml schema 的擴展便完成了。

dubbo中的xml schema擴展

最后我們以 dubbo 為例,看看一個成熟的 xml schema 擴展是如何被應用的。

Spring中XML schema擴展機制的深入講解

剛好對應了四個標準的擴展步驟,是不是對 xml 配置下的 dubbo 應用有了更好的理解了呢?

順帶一提,僅僅完成 bean 的注冊還是不夠的,在“注冊”的同時,dubbo 還進行了一系列其他操作如:暴露端口,開啟服務器,完成注冊中心的注冊,生成代理對象等等行為,由于不在本文的范圍內,后續的 dubbo 專題會專門介紹這些細節,本文便是了解 dubbo 加載流程的前置文章了。

總結:

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnkirito.moe/spring-xsd/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 果冻传媒ⅹxxxxxhd | 精品久久久久久久久久香蕉 | 亚洲国产区男人本色在线观看欧美 | 国产亚洲精品激情一区二区三区 | 男女性刺激爽爽免费视频 | 爽爽窝窝午夜精品一区二区 | 四虎影院免费在线播放 | xxxxxx性受 | 极品美女穴| 黄在线观看www免费看 | 青草午夜精品视频在线观看 | 日韩手机在线视频 | 亚洲欧美久久久久久久久久爽网站 | 国产福利在线观看第二区 | 亚洲精品一区二区三区中文字幕 | 三级黄色图片 | 2018天天弄 | 国产在线观看网站 | 亚洲成av人影院 | 亚洲AV人无码综合在线观看蜜桃 | 91夜夜操| 国产免费久久精品44 | 果冻传媒和91制片厂网站软件 | 五月婷婷在线观看 | 草莓在深夜释放自己软件 | 国产精品第一区揄拍 | 国内精品一区视频在线播放 | 娇妻被朋友征服中文字幕 | 亚洲欧美综合在线观看 | 操熟美女又肥又嫩的骚屁股 | 国产成人精品高清在线观看99 | 国产区香蕉精品系列在线观看不卡 | 美尻在线 | 青青热久麻豆精品视频在线观看 | 国产美女屁股直流白浆视频无遮挡 | 99久久免费看国产精品 | 国产精品福利短视在线播放频 | 国产精品视频二区不卡 | 国产成人福利美女观看视频 | 手机av影院 | 欧美最猛性xxxxx动态图 |