SpringBoot之自定義Schema擴展方式
SpringBoot 自定義Schema擴展
最近在寫RPC框架時,用到了自定義的xsd配置。我們平時習慣于使用bean配置實例化對象,因此把xsd這種方式單獨拎出來。
1. 配置ServiceConfig屬性
@Data public class ServiceConfig { /** 接口 */ private String interfaceClass; /** 引用 */ private String ref; /** 版本 */ private String version; @Override public String toString() { return "ServiceConfig{" + "interfaceClass='" + interfaceClass + '\'' + ", ref='" + ref + '\'' + ", version='" + version + '\'' + '}'; } }
2. 編寫XSD文件
配置element的name為service,配置的attribute對應ServiceConfig定義的屬性
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://gitee.com/schema/link" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://gitee.com/schema/link" elementFormDefault="qualified"> <xsd:import namespace="http://www.springframework.org/schema/beans" /> <xsd:import namespace="http://www.springframework.org/schema/tool" /> <xsd:element name="service"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="ref" type="xsd:string" use="required"> <xsd:annotation> <xsd:documentation><![CDATA[ 服務接口實現(xiàn)類]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="interfaceClass" type="xsd:string" use="required"> <xsd:annotation> <xsd:documentation><![CDATA[服務接口]]></xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="version" type="xsd:string" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
3. 編寫NamespaceHandler
registerBeanDefinitionParser方法的key是xsd配置的element的name,表示service元素由LinkServiceBeanDefinitionParser對象解析
public class LinkNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { this.registerBeanDefinitionParser("service", new LinkServiceBeanDefinitionParser()); } }
4. 編寫B(tài)eanDefinitionParser
從element中解析出屬性,注冊到BeanDefinitionBuilder
public class LinkServiceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override protected Class getBeanClass(Element element) { return ServiceConfig.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { bean.addPropertyValue("ref", element.getAttribute("ref")); bean.addPropertyValue("interfaceClass", element.getAttribute("interfaceClass")); bean.addPropertyValue("version", element.getAttribute("version")); } }
5. 配置spring.handlers和spring.schemas
http\://gitee.com/schema/link=com.test.xsd.handler.LinkNamespaceHandler http\://gitee.com/schema/link/link.xsd=META-INF/link.xsd
6. 配置spring的加載文件
在文件頭部需要引入link的schema
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:link="http://gitee.com/schema/link" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://gitee.com/schema/link http://gitee.com/schema/link/link.xsd"> <!-- rpc服務 --> <link:service id="serviceConfig" ref="helloService" interfaceClass="com.test.service.HelloService" version="1.0.0"/> </beans>
7. 測試
public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("link-server.xml"); ServiceConfig config = (ServiceConfig) context.getBean("serviceConfig"); System.out.println(config.toString()); } }
Spring Schema擴展機制
1. 概述
Spring2.0開始,Spring提供XML Schema可擴展機制,用戶可以自定義XML Schema文件,并自定義
XML Bean解析器,集成到Spring IOC容器中。
2. 步驟
創(chuàng)建一個XML Schema文件,描述自定義的合法構建模塊,也就是xsd文件。
自定義處理器類,并實現(xiàn)NamespaceHandler接口。
自定義一個或者多個解析器,實現(xiàn)BeanDefinitionParser接口(關鍵部分)。
注冊上面的組建到Spring IOC容器。
3. 示例如下
(1) 自定義XML Schema文件
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.liuenyuan.com/schema/myns" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.liuenyuan.com/schema/myns" elementFormDefault="qualified"> <xsd:import namespace="http://www.springframework.org/schema/beans"/> <xsd:element name="dateFormat"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="pattern" type="xsd:string" use="required"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
自定義targetNamespace是http://www.liuenyuan.com/schema/myns,xmlns與命名空間必須一致。
(2) 自定義NamespaceHandler
NamespaceHandler接口只有三個方法
init()
:在NamespaceHandler被使用之前調用,完成初始化parse()
:解析元素decorate()
:嵌套元素時候調用
Spring提供一個默認實現(xiàn)類NamespaceHandlerSupport,注入每個元素的解析器即可。
用到了代理委托概念。NamespaceHandlerSupport可以注冊任意個BeanDefinitionParser,負責所有自定義元素編排,實際XML解析工作委托給各個BeanDefinitioParser負責。
(3) 自定義BeanDefinitionParser
BeanDefinitionParser 將被調用,如果NamespapceHandler遇到元素類型已經(jīng)有對應注冊的parser(例如上面的handler如果遇到dateformat,DateformatDefinitionParser會被調用,
解析相應的屬性設置到Bean中)將會被調用。BeanDefinitionParser負責解析一個頂級元素。
Spring提供AbstractSingleBeanDefinitionParser處理繁重的解析工作。
getBeanClass()
:返回元素Class類型doParse()
:添加元素屬性或者構造參數(shù)
(4) 注冊handler和schema
把實現(xiàn)的NamespaceHandler和xsd文件配置到指定的配置文件中。位于META-INF目錄中。
spring.handlers文件包含xml schema uri和Handler類映射關系。
http\://www.liuenyuan.com/schema/myns=\ com.ley.springboot.schema.xml.MynsNamespaceHandler
遇到http\://www.liuenyuan.com/schema/myns命名空間的時候會交給MynsNamespaceHandler來處理,key部分必須和xsd文件中的targetNamespace值保持一致
spring.schemas文件包含xml schema xsd文件命名空間和文件路徑映射關系。
http\://www.liuenyuan.com/schema/myns.xsd=META-INF/myns.xsd
(5) 測試
NamespaceHandler實現(xiàn)類
public class MynsNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("dateFormat", new MynsBeanDefinitionParser()); } }
BeaDefinitionParser實現(xiàn)類
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.w3c.dom.Element; import java.text.SimpleDateFormat; public class MynsBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override protected Class<?> getBeanClass(Element element) { return SimpleDateFormat.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { String pattern = element.getAttribute("pattern"); builder.addConstructorArgValue(pattern); } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java8 stream 操作map根據(jù)key或者value排序的實現(xiàn)
這篇文章主要介紹了java8 stream 操作map根據(jù)key或者value排序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09springboot+mybatis+枚舉處理器的實現(xiàn)
在Spring?boot項目開發(fā)中經(jīng)常遇到需要使用枚舉的場景,本文就介紹了springboot+mybatis+枚舉處理器的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03spring聲明式事務 @Transactional 不回滾的多種情況以及解決方案
本文主要介紹了spring聲明式事務 @Transactional 不回滾的多種情況以及解決方案,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11