基于Spring开发
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的基本流程为:
- 解析标签
- 根据解析的值生成BeanDefinition,
- 注册标签
解析标签就不用说,重点说说怎么生成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开发的更多相关文章
- 基于Spring开发的DUBBO服务接口测试
基于Spring开发的DUBBO服务接口测试 知识共享主要内容: 1. Dubbo相关概念和架构,以及dubbo服务程序开发步骤. 2. 基于Spring开发框架的dubbo服务接口测试相关配置. 3 ...
- 基于Spring开发的一个BIO-RPC框架(对新人很友好)
PART1:先来整体看下项目的构成 其中bio-rpc-core就是所谓的rpc框架 bio-rpc-example-client即所谓的服务调用方(你的项目中想要调用服务的地方) bio-rpc-e ...
- 基于Spring开发——自定义标签及其解析
1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...
- 教程:基于Spring快速开发电子邮件发送功能
在Spring框架的spring-context-support.jar中有对电子邮件发送功能的封装: 基于Spring开发简单省事,而且更稳定.需要mail.jar包支持 @Component pu ...
- 如何基于Spring Boot搭建一个完整的项目
前言 使用Spring Boot做后台项目开发也快半年了,由于之前有过基于Spring开发的项目经验,相比之下觉得Spring Boot就是天堂,开箱即用来形容是绝不为过的.在没有接触Spring B ...
- 带你手写基于 Spring 的可插拔式 RPC 框架(二)整体结构
前言 上一篇文章中我们已经知道了什么是 RPC 框架和为什么要做一个 RPC 框架了,这一章我们来从宏观上分析,怎么来实现一个 RPC 框架,这个框架都有那些模块以及这些模块的作用. 总体设计 在我们 ...
- 基于Spring的可扩展Schema进行开发自定义配置标签支持
一.背景 最近和朋友一起想开发一个类似alibaba dubbo的功能的工具,其中就用到了基于Spring的可扩展Schema进行开发自定义配置标签支持,通过上网查资料自己写了一个demo.今天在这里 ...
- 基于Spring MVC的Web应用开发(三) - Resources
基于Spring MVC的Web应用开发(3) - Resources 上一篇介绍了在基于Spring MVC的Web项目中加入日志,本文介绍Spring MVC如何处理资源文件. 注意到本项目的we ...
- RESTLET开发实例(三)基于spring的REST服务
http://www.lifeba.org/arch/restlet_spring_3.html 前面两篇文章,我们介绍了基于JAX-RS的REST服务以及Application的Rest服务.这里将 ...
随机推荐
- ios9 xcode7以后编译需要进行的几项设置
http://blog.csdn.net/hero82748274/article/details/48629461 1.库后缀变了:.dylib->tbd libsqlite3.0.dylib ...
- Windows下启动ActiveMq端口被占用的解决办法
cd /D E:\RuntimeSoft\apache-activemq-5.11.0\binactivemq.bat start结果提示:端口号被占用. Windows下查看端口号被占用开始--运行 ...
- [Ramda] Sort, SortBy, SortWith in Ramda
The difference between sort, sortBy, sortWith is that: 1. sort: take function as args. 2. sortBy: ta ...
- Oracle中的游标(转)
Oracle中的游标有两种:显式游标.隐式游标.显示游标是用cursor...is命令定义的游标,它可以对查询语句(select)返回的多条记录进行处理,而隐式游标是在执行插入 (insert).删除 ...
- 用Mochiweb打造百万级Comet应用,第一部分
http://www.iteye.com/topic/267028 原文:A Million-user Comet Application with Mochiweb, Part 1 参考资料:Com ...
- hadoop实现购物商城推荐系统
1,商城:是单商家,多买家的商城系统.数据库是mysql,语言java. 2,sqoop1.9.33:在mysql和hadoop中交换数据. 3,hadoop2.2.0:这里用于练习的是伪分布模式. ...
- callback回调函数理解 相当于this指针
1.callback函数在微软的官方手册中是这样定义callback函数的:“callback函数是由应用程序定义而由操作系统调用的函数”. 凡是由用户设计而却由windows系统调用的函数,统称 ...
- 再议指针---------函数回调(qsort函数原理)
我们是否能写一个这种函数: 能够对不论什么类型数据排序 不论什么人在使用该函数不须要改动该函数代码(即:用户能够不必看到函数源 码,仅仅会调用即可) 思考: 用户须要排序的数据的类型千变万化,可能是i ...
- spring集成Quartz时区问题造成任务晚执行八小时
项目中在Spring中集成了Quartz,配置的每日凌晨执行的定时任务都是到了八点多才执行,经过一番查找,可能是时区问题造成的. 一种解决办法是在JVM启动参数中增加 --Duser.timezone ...
- android Notification分析——
您可能会遇到各种问题
使用的各种总结上线通知,csdn还有一个非常到位的总结,不这样做,反复总结,学生需要能够搜索自己或参考下面给出的链接. 研究开始时仔细阅读一些,今天,功能开发,一些问题和经验自己最近的遭遇给大家分享. ...