SpringBoot之自定義Schema擴(kuò)展方式
SpringBoot 自定義Schema擴(kuò)展
最近在寫RPC框架時(shí),用到了自定義的xsd配置。我們平時(shí)習(xí)慣于使用bean配置實(shí)例化對(duì)象,因此把xsd這種方式單獨(dú)拎出來(lái)。
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對(duì)應(yīng)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[ 服務(wù)接口實(shí)現(xiàn)類]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="interfaceClass" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[服務(wù)接口]]></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對(duì)象解析
public class LinkNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
this.registerBeanDefinitionParser("service", new LinkServiceBeanDefinitionParser());
}
}
4. 編寫B(tài)eanDefinitionParser
從element中解析出屬性,注冊(cè)到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服務(wù) -->
<link:service id="serviceConfig"
ref="helloService"
interfaceClass="com.test.service.HelloService"
version="1.0.0"/>
</beans>
7. 測(cè)試
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擴(kuò)展機(jī)制
1. 概述
Spring2.0開(kāi)始,Spring提供XML Schema可擴(kuò)展機(jī)制,用戶可以自定義XML Schema文件,并自定義
XML Bean解析器,集成到Spring IOC容器中。
2. 步驟
創(chuàng)建一個(gè)XML Schema文件,描述自定義的合法構(gòu)建模塊,也就是xsd文件。
自定義處理器類,并實(shí)現(xiàn)NamespaceHandler接口。
自定義一個(gè)或者多個(gè)解析器,實(shí)現(xiàn)BeanDefinitionParser接口(關(guān)鍵部分)。
注冊(cè)上面的組建到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接口只有三個(gè)方法
init():在NamespaceHandler被使用之前調(diào)用,完成初始化parse():解析元素decorate():嵌套元素時(shí)候調(diào)用
Spring提供一個(gè)默認(rèn)實(shí)現(xiàn)類NamespaceHandlerSupport,注入每個(gè)元素的解析器即可。
用到了代理委托概念。NamespaceHandlerSupport可以注冊(cè)任意個(gè)BeanDefinitionParser,負(fù)責(zé)所有自定義元素編排,實(shí)際XML解析工作委托給各個(gè)BeanDefinitioParser負(fù)責(zé)。
(3) 自定義BeanDefinitionParser
BeanDefinitionParser 將被調(diào)用,如果NamespapceHandler遇到元素類型已經(jīng)有對(duì)應(yīng)注冊(cè)的parser(例如上面的handler如果遇到dateformat,DateformatDefinitionParser會(huì)被調(diào)用,
解析相應(yīng)的屬性設(shè)置到Bean中)將會(huì)被調(diào)用。BeanDefinitionParser負(fù)責(zé)解析一個(gè)頂級(jí)元素。
Spring提供AbstractSingleBeanDefinitionParser處理繁重的解析工作。
getBeanClass():返回元素Class類型doParse():添加元素屬性或者構(gòu)造參數(shù)
(4) 注冊(cè)handler和schema
把實(shí)現(xiàn)的NamespaceHandler和xsd文件配置到指定的配置文件中。位于META-INF目錄中。
spring.handlers文件包含xml schema uri和Handler類映射關(guān)系。
http\://www.liuenyuan.com/schema/myns=\ com.ley.springboot.schema.xml.MynsNamespaceHandler
遇到http\://www.liuenyuan.com/schema/myns命名空間的時(shí)候會(huì)交給MynsNamespaceHandler來(lái)處理,key部分必須和xsd文件中的targetNamespace值保持一致
spring.schemas文件包含xml schema xsd文件命名空間和文件路徑映射關(guān)系。
http\://www.liuenyuan.com/schema/myns.xsd=META-INF/myns.xsd
(5) 測(cè)試
NamespaceHandler實(shí)現(xiàn)類
public class MynsNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("dateFormat", new MynsBeanDefinitionParser());
}
}
BeaDefinitionParser實(shí)現(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);
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java8 stream 操作map根據(jù)key或者value排序的實(shí)現(xiàn)
這篇文章主要介紹了java8 stream 操作map根據(jù)key或者value排序的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
基于Java實(shí)現(xiàn)簡(jiǎn)單的郵件群發(fā)功能
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言編寫一個(gè)簡(jiǎn)單的工具類,可以實(shí)現(xiàn)郵件群發(fā)功能。文中的示例代碼講解詳細(xì),需要的可以參考一下2022-05-05
spring boot 注冊(cè)攔截器過(guò)程詳解
這篇文章主要介紹了spring boot中注冊(cè)攔截器過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
springboot+mybatis+枚舉處理器的實(shí)現(xiàn)
在Spring?boot項(xiàng)目開(kāi)發(fā)中經(jīng)常遇到需要使用枚舉的場(chǎng)景,本文就介紹了springboot+mybatis+枚舉處理器的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
spring聲明式事務(wù) @Transactional 不回滾的多種情況以及解決方案
本文主要介紹了spring聲明式事務(wù) @Transactional 不回滾的多種情況以及解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11

