这期内容当中小编将会给大家带来有关SpringBoot中如何自定义Schema扩展方式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
最近在写RPC框架时,用到了自定义的xsd配置。我们平时习惯于使用bean配置实例化对象,因此把xsd这种方式单独拎出来。
@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 + '\'' +
'}';
}
}
配置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[ 服务接口实现类]]></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>
registerBeanDefinitionParser方法的key是xsd配置的element的name,表示service元素由LinkServiceBeanDefinitionParser对象解析
public class LinkNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
this.registerBeanDefinitionParser("service", new LinkServiceBeanDefinitionParser());
}
}
从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"));
}
}
http\://gitee.com/schema/link=com.test.xsd.handler.LinkNamespaceHandler
http\://gitee.com/schema/link/link.xsd=META-INF/link.xsd
在文件头部需要引入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>
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());
}
}
Spring2.0开始,Spring提供XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义
XML Bean解析器,集成到Spring IOC容器中。
创建一个XML Schema文件,描述自定义的合法构建模块,也就是xsd文件。
自定义处理器类,并实现NamespaceHandler接口。
自定义一个或者多个解析器,实现BeanDefinitionParser接口(关键部分)。
注册上面的组建到Spring IOC容器。
(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提供一个默认实现类NamespaceHandlerSupport,注入每个元素的解析器即可。
用到了代理委托概念。NamespaceHandlerSupport可以注册任意个BeanDefinitionParser,负责所有自定义元素编排,实际XML解析工作委托给各个BeanDefinitioParser负责。
(3) 自定义BeanDefinitionParser
BeanDefinitionParser 将被调用,如果NamespapceHandler遇到元素类型已经有对应注册的parser(例如上面的handler如果遇到dateformat,DateformatDefinitionParser会被调用,
解析相应的属性设置到Bean中)将会被调用。BeanDefinitionParser负责解析一个顶级元素。
Spring提供AbstractSingleBeanDefinitionParser处理繁重的解析工作。
getBeanClass()
:返回元素Class类型
doParse()
:添加元素属性或者构造参数
(4) 注册handler和schema
把实现的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实现类
public class MynsNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("dateFormat", new MynsBeanDefinitionParser());
}
}
BeaDefinitionParser实现类
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);
}
}
上述就是小编为大家分享的SpringBoot中如何自定义Schema扩展方式了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。