1. XML Schema

1.1 最简单的标签

一个最简单的标签,形式如:

<bf:head-routing key="1" value="1" to="test2"/>

该标签只包含了若干属性,我们就在xsd文件中这么定义

<!-- 声明一个标签,名字为head-routing,他的类型为headRouting-->
<xsd:element name="head-routing" type="headRouting"></xsd:element> <!-- 定义head-routing的类型,这里定义它有key,value,to,patten四个属性 -->
<xsd:complexType name="headRouting">
<xsd:attribute name="key" type="xsd:string" use="required"></xsd:attribute>
<xsd:attribute name="value" type="xsd:string" use="required"></xsd:attribute>
<xsd:attribute name="to" type="xsd:IDREF" use="required"></xsd:attribute>
<xsd:attribute name="patten" type="xsd:string" default="string"></xsd:attribute>
</xsd:complexType>
在<xsd:attribute>标签
中的type是用来定义该属性的格式,例如
  • xsd:string 表示是一个字符串,对格式没什么要求
  • xsd:id 表示该属性的值是一个id,有格式要求(例如不能以数字开头)。
  • xsd:IDREF 表示该属性的值与某xsd:id属性的值对应
  • 其他还有很多,例如number,double,datetime等等。

1.2 复杂点的标签

所谓复杂,其实就是嵌套的标签,形式如:

    <bf:stop id="test1" ref="testNode">
<bf:head-routing key="1" value="1" to="test2"/>
</bf:stop>

其实只要参照Spring 中<bean>标签的xsd依葫芦画瓢,首先是定义stop标签

    <xsd:element name="stop">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:group ref="stopElements"/>
<xsd:attributeGroup ref="stopAttributes"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>

其中,

  • <xsd:extension base="beans:identifiedType"> 定义了该标签的id属性,注意这里引用的是spring-beans中的type,
  • <xsd:group ref="stopElements"/>中定义了<bf:stop>标签允许的子标签
  • <xsd:attributeGroup ref="stopAttributes"/> 定义了<bf:stop>标签允许的属性
    <xsd:group name="stopElements">
<xsd:sequence>
<xsd:element ref="description" minOccurs="0"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="head-routing"/>
<!-- 有更多的子标签继续在这里添加,例如<xsd:element ref="properties"/> -->
</xsd:choice>
</xsd:sequence>
</xsd:group> <xsd:attributeGroup name="stopAttributes">
<xsd:attribute name="ref" type="xsd:IDREF" use="required">
<xsd:annotation>
<xsd:appinfo>
<!-- 这里是使用了Spring tool xsd中的标签,格式校验-->
<tool:annotation kind="ref">
<tool:expected-type type="com.lizo.node.Station"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<!-- 有更多的子标签继续在这里添加,例如<xsd:attribute name="value" type="xsd:string"/> -->

2. 配置文件

完成了xsd文件编写后,还需要让该文件生效,就需要在项目的resource/META-INF包里面配置2个文件spring.handlers和spring.schemas

2.1 spring.schemas

改配置文件主要是用一个url来映射我们第一步配置好的文件,形式如下

http\://www.lizo.com/schema/bf.xsd=META-INF/bf.xsd

这样,就可以在Spring的xml配置文件中加入spring.schemas的url,省略掉其他的,在<beans>标签中增加如下信息

    <beans
..
xmlns:bf="http://www.lizo.com/schema/bf"
xsi:schemaLocation="
...
http://www.lizo.com/schema/bf
http://www.lizo.com/schema/bf.xsd
">

完成这步以后,就可以在xml中写自己的标签了,例如自定义标签的namespace为bf,

   <bf:stop id="test123" ref="testNode">
<bf:head-routing key="1" value="1" to="test1"/>
<bf:head-routing key="3" value="4" to="test2"/>
</bf:stop>

2.2 spring.handlers

这个配置文件用来配置解析我们bf标签,然后生成一些BeanDefinition进行注册。例如

http\://www.lizo.com/schema/bf=com.lizo.config.BusinessFlowNamespaceHandlerSupport

其中 BusinessFlowNamespaceHandlerSupport就是我们用来解析标签

3. 自定义标签解析

在上一步中,我们配置了com.lizo.config.BusinessFlowNamespaceHandlerSupport类作为解析自定义标签的类,所以namespace为bf的标签,都会用这里注册的标签解析器来解析

public class BusinessFlowNamespaceHandlerSupport extends NamespaceHandlerSupport {
public void init() {
//注册用于解析<bf:stop>的解析器
registerBeanDefinitionParser("stop", new BusinessFlowBeanDefinitionParser());
}
}

我们自定义的标签解析器BusinessFlowBeanDefinitionParser是要实现BeanDefinitionParser 接口的

public interface BeanDefinitionParser {
BeanDefinition parse(Element element, ParserContext parserContext);
}

一般来说,注册bean的基本流程为:

  1. 解析标签
  2. 根据解析的值生成BeanDefinition,
  3. 注册标签

解析标签就不用说,重点说说怎么生成BeanDefinition

3.1 生成BeanDefinition

一个最简单的BeanDefinition通过设置Class和属性的注入就可以完成。如下:

RootBeanDefinition nodeWrapDefinition = new RootBeanDefinition();
//该BeanDefinition对应的是什么类
nodeWrapDefinition.setBeanClass(StationRoutingWrap.class);
//name是解析标签后获得的值
nodeWrapDefinition.getPropertyValues().addPropertyValue("name", name);

RuntimeBeanReference

RuntimeBeanReference 用于在运行时去获取BeanDefinition,因为在我们创建这个BeanDefinition的时候我们只知道他的beanName,并不确定是否已经注册了,这个时候就需要用RuntimeBeanReference,例如

RuntimeBeanReference refBean = new RuntimeBeanReference(ref);
nodeWrapDefinition.getPropertyValues().addPropertyValue("station", refBean);

集合类BeanDefinition

某个BeanDefinition注入的属性为一个List,这个时候就需要用ManagedList(同理有ManagedMap,ManagedSet),

ManagedList routingConditions = new ManagedList();
....
nodeWrapDefinition.getPropertyValues().add("routing", routing);

3.2 注册bean

注册BeanDefinitionParser 接口的函数中有个参数ParserContext,有个方法为getRegistry(),因此,注冊bean的時候就很简单了

parserContext.getRegistry().registerBeanDefinition("beanName",nodeWrapDefinition);

总结

通过以上三步,就可以实现自己定义标签,并且在Spring容器中注入相关的bean。让我们的框架使用起来更方便(更装B)

基于Spring开发——自定义标签及其解析的更多相关文章

  1. Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md

    写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...

  2. Spring 系列教程之自定义标签的解析

    Spring 系列教程之自定义标签的解析 在之前的章节中,我们提到了在 Spring 中存在默认标签与自定义标签两种,而在上一章节中我们分析了 Spring 中对默认标签的解析过程,相信大家一定已经有 ...

  3. Spring IoC 自定义标签解析

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  4. JSP进阶 之 SimpleTagSupport 开发自定义标签

    绝大部分 Java 领域的 MVC 框架,例如 Struts.Spring MVC.JSF 等,主要由两部分组成:控制器组件和视图组件.其中视图组件主要由大量功能丰富的标签库充当.对于大部分开发者而言 ...

  5. 基于Spring开发的DUBBO服务接口测试

    基于Spring开发的DUBBO服务接口测试 知识共享主要内容: 1. Dubbo相关概念和架构,以及dubbo服务程序开发步骤. 2. 基于Spring开发框架的dubbo服务接口测试相关配置. 3 ...

  6. Spring的自定义标签

    当Spring拿到一个元素时首先要做的是根据命名空间进行解析,如果是默认的命名空间,则使用parseDefaultElement方法进行元素解析,否则使用parseCustom Element方法进行 ...

  7. Spring——使用自定义标签

    文章内容参考了<Spring源码深度解析>一书.自己照着书中内容做了一遍,不懂的地方以及采坑的地方会在文中记录. 推荐一篇post,关于Spring配置文件的命名空间: https://w ...

  8. spring thymeleaf 自定义标签

    概述 thymeleaf2.1.5自定义标签及自定义属性案例,类似于JSP中的自定义JSTL标签 详细 代码下载:http://www.demodashi.com/demo/10495.html 一. ...

  9. 基于Spring开发

    1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...

随机推荐

  1. tornado学习 - TCPClient 实现聊天功能

    之前完成了一个简单的聊天服务器,连接服务器使用的是系统自带nc命令,接下来就是通过自己实现TCPClient. 客户端与服务器功能大致相仿,相对与服务器只是少了转发消息环节. 首先,定义TCPClie ...

  2. DbUtils类基本使用

    一.commons-dbutils简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化 ...

  3. iOS回顾笔记(04) -- UIScrollView的基本使用详解

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  4. UI培训自学能学好吗

    近年来UI设计师愈来愈红,成为行业热门,越来越多的人开始专注UI培训,也有一部分人在考虑,培训班一般价格不菲,我自学怎么样呢? UI设计是指人机交互过程中的一个界面设计,常用到的有 ps和ai两个工具 ...

  5. 【经验】css

    1.父元素overflow:hidden,当父元素大小减小到不容纳子元素时,会出现滚动条.2.input的盒模型尺寸基准是content-box,它的宽度将是以width-border计算,也就是说一 ...

  6. 免费ERP之云实施

    近日,普实渠道在AIO5软件免费一周年之际,推出了重磅的动作:启动AIO5云实施,推广小微企业免费ERP落地应用. 这无疑是推动客户免费应用ERP的重大里程碑. 当前,在中国小微企业信息化方面,应用情 ...

  7. VS.NET2010水晶报表安装部署[VS2010]

    水晶报表VS2010版IDE安装标准版SAP Crystal Reports, version for Visual Studio 2010 - Standard: 下载地址: http://down ...

  8. GUID的获取

    全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符. GUID 的格式为“xxxxxxxx-xxxx-xxxx-xxxx ...

  9. ServletConfig使用

    一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...

  10. css兼容问题 ie6,7

    H5标签兼容 元素浮动之后能设置宽度的话就给元素加宽度,如果需要元素宽度是内容撑开,就给他里面的块元素加上浮动 第一块加浮动,第二块加margin等于第一块元素在IE6下会有间隙问题 IE6下子元素超 ...