文档章节

基于Spring开发——自定义标签及其解析

lizo
 lizo
发布于 2017/04/08 16:01
字数 1338
阅读 314
收藏 1

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

1. XML Schema

要想自定义标签,首先第一步需要写自己的XML Schema。XML Schema的个人感觉比较复杂,网上的教程比较简单,因此可以参照spring-beans.xsd依葫芦画瓢。这里就按照我自己的理解进行简单介绍一下吧。 ##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)

© 著作权归作者所有

lizo

lizo

粉丝 60
博文 40
码字总数 50118
作品 0
杭州
程序员
私信 提问
加载中

评论(0)

【死磕 Spring】—– IOC 之 IOC 初始化总结

原文出自:http://cmsblogs.com 前面 13 篇博文从源码层次分析了 IOC 整个初始化过程,这篇就这些内容做一个总结将其连贯起来。 在前文提过,IOC 容器的初始化过程分为三步骤:Resource 定位...

chenssy
2018/10/09
0
0
阿里大牛笔记精选:Redis+Sping源码+Spring+SpringBoot技术分享

Redis实战 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。...

毛发旺盛的程序员
05/21
0
0
这一次搞懂Spring的XML解析原理

前言 Spring已经是我们Java Web开发必不可少的一个框架,其大大简化了我们的开发,提高了开发者的效率。同时,其源码对于开发者来说也是宝藏,从中我们可以学习到非常优秀的设计思想以及优雅...

夜勿语
昨天
0
0
springboot微服务系列教程

微服务系列教程 Spring Boot 2是微服务的基础,在2018年3月初,Spring Boot 正式宣布进入2.0时代。下面一起来步入Spring Boot 2时代,领略Spring Boot 2带来的开发乐趣吧! 本系统源代码地址...

鱼煎
2019/01/13
1.7K
0
Spring MVC 解读——

Spring MVC 解读——mvc:annotation-driven/ 一、AnnotationDrivenBeanDefinitionParser 通常如果我们希望通过注解的方式来进行Spring MVC开发,我们都会在***-servlet.xml中加入mvc:annotat...

麦壳原野
2014/03/05
6.8W
8

没有更多内容

加载失败,请刷新页面

加载更多

window下 mongodb开启用户名和密码 权限

在默认情况下,mongod是监听在127.0.0.1之上的,任何客户端都可以直接连接27017,且没有认证。 好处是,用户可以即时上手,不用担心被一堆配置弄的心烦意乱。 坏处是,公网服务器搭建MongoDB...

东东笔记
54分钟前
9
0
数据倾斜

数据倾斜: 两种数据倾斜发生的现象: 80%情况下都发生挂了,只有极少20%情况下能把task执行完成 窄依赖:结构简单,如果发生数据丢失,方便查找丢失的数据 宽依赖:结构复杂,如何发生数据丢...

七宝1
今天
20
0
我的jdk源码(十一):ArrayList

一、概述 ArrayList类是AbstractList的子类,实现了具体的add(), set(), remove()等方法。它是一个可调整大小的数组可以用来存放各种形式的数据。 二、源码分析 (1) 类的声明,源码如下: ...

Java觉浅
昨天
24
0
vnc server,vnc server是什么,vnc工具推荐

nc server是一个用来共享linux服务器上资源给其他分布式用户的服务只要再一台linux系统的机器上安装vnc server,然后开启服务,其他机器就可以通过vncviewer访问这台机器上的共享资源,那么今...

兔子m
昨天
20
0
COLA的扩展性使用和源码研究

cola扩展点使用和设计初探 封装变化,可灵活应对程序的需求变化。 扩展点使用 步骤: 定义扩展点接口,类型可以是校验器,转换器,实体; 必须以ExtPt结尾,表示一个扩展点。 比如,我定义一个...

李福春carter
昨天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部