自定义配置文件到spring 中,有时候想做一些数据结构的配置化信息,根据业务做一个扩展。

首先:

在项目的META-INF目录下新建两个文件spring.handlers,和spring.shcemas

Spring.handlers在类org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver中已经写死了要取mapping的handlerMappingsLocation的路径

public static finalString DEFAULT_HANDLER_MAPPINGS_LOCATION ="META-INF/spring.handlers";

Spring.Schemas 在org.springframework.beans.factory.xml.PluggableSchemaResolver这个类中

同样写死了位置

public static finalString DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";

初始化的时候第一次调用的时候会调用

PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation,this.classLoader)

把所有的文件名包含的取出来放入map中。

spring.handlers内容:

http\://www.ruishenh.com/custom/mytest=com.ruishenh.spring.config.MyNamespaceHandler

spring.schemas内容:

http\://www.ruishenh.com/custom/mytest/myTest.xsd=customTag/myTest.xsd

customTag/myTest.xsd文件:

<?xml version="1.0"encoding="UTF-8"?>
<xsd:schema xmlns="http://www.ruishenh.com/custom/myTest"xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.ruishenh.com/custom/mytest"elementFormDefault="qualified" attributeFormDefault="unqualified"><xsd:element name="executor"><xsd:complexType><xsd:attribute name="name" type="xsd:string"></xsd:attribute><xsd:attribute name="delay" type="xsd:int"></xsd:attribute><xsd:attribute name="interval" type="xsd:int"use="required"></xsd:attribute><xsd:attribute name="address" type="xsd:string"></xsd:attribute><xsd:attribute name="entity" type="xsd:string"></xsd:attribute></xsd:complexType></xsd:element><xsd:element name="entity"><xsd:complexType><xsd:attribute name="name" type="xsd:string"><xsd:annotation><xsd:documentation><![CDATA[ bean Name ]]></xsd:documentation></xsd:annotation></xsd:attribute><xsd:attribute name="splitBy" type="xsd:string"><xsd:annotation><xsd:documentation xml:lang="zh"><![CDATA[ sqoop分割字段 ]]></xsd:documentation></xsd:annotation></xsd:attribute><xsd:attribute name="sql" type="xsd:string"><xsd:annotation><xsd:documentation xml:lang="zh"><![CDATA[数据库操作sql]]></xsd:documentation></xsd:annotation></xsd:attribute><xsd:attribute name="dbTypeID"><xsd:annotation><xsd:documentation xml:lang="zh"><![CDATA[ 指定数据库类型 如果类型不存在就判断dbTypeName属性,1是mysql,2是oracle,3是sqlserver    ]]></xsd:documentation></xsd:annotation><xsd:simpleType><xsd:restriction base="xsd:int"><xsd:enumeration value="1" /><xsd:enumeration value="2" /><xsd:enumeration value="3" /></xsd:restriction></xsd:simpleType></xsd:attribute><xsd:attribute name="dbTypeName"><xsd:annotation><xsd:documentation xml:lang="zh"><![CDATA[ 指定数据库指定名称  如果  dbTypeID 不存在就取当前值 ]]></xsd:documentation></xsd:annotation><xsd:simpleType><xsd:restriction base="xsd:string"><xsd:enumeration value="mysql" /><xsd:enumeration value="oracle" /><xsd:enumeration value="sqlserver" /></xsd:restriction></xsd:simpleType></xsd:attribute></xsd:complexType></xsd:element>
</xsd:schema>

spring/myTest.xml文件:

<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mi="http://www.ruishenh.com/custom/mytest"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.ruishenh.com/custom/mytesthttp://www.ruishenh.com/custom/mytest/myTest.xsd"><mi:entity dbTypeID="1" dbTypeName="mysql"splitBy="id" sql="1"name="mye" /><mi:executor interval="5000" address="127.0.0.1"delay="2000"name="myexecutor" entity="mye" />
</beans>

com.ruishenh.spring.config.MyNamespaceHandler  命名空间处理类:

package com.ruishenh.spring.config;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;public class MyNamespaceHandler extends NamespaceHandlerSupport{@Overridepublic void init() {registerBeanDefinitionParser("executor",newMyBeanDefinitionParser(MyExecutor.class));registerBeanDefinitionParser("entity",newMyBeanDefinitionParser(MyEntity.class));}}

这个类主要是在DefaultNamespaceHandlerResolver这个类中getHandlerMappings()取到了所有的META-INF/spring.handlers的文件内容存入map,然后根据当前的命名空间找到对应的NamespaceHandler,然后反射出对象调用init()

Class<?> handlerClass =ClassUtils.forName(className, this.classLoader);if (!NamespaceHandler.class.isAssignableFrom(handlerClass)){throw new FatalBeanException("Class ["+ className + "] for namespace [" + namespaceUri +"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");}NamespaceHandlernamespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);namespaceHandler.init();

com.ruishenh.spring.config.MyBeanDefinitionParser解析类:

packagecom.ruishenh.spring.config;importorg.springframework.beans.factory.config.BeanDefinition;
importorg.springframework.beans.factory.config.RuntimeBeanReference;
importorg.springframework.beans.factory.support.RootBeanDefinition;
importorg.springframework.beans.factory.xml.BeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Element;
importorg.w3c.dom.NamedNodeMap;
importorg.w3c.dom.Node;public classMyBeanDefinitionParser implements BeanDefinitionParser {private Class<?> clssze;publicMyBeanDefinitionParser(Class<?> cls) {this.clssze = cls;}@Overridepublic BeanDefinition parse(Elementelement, ParserContext parserContext) {RootBeanDefinitionbeanDefinition = new RootBeanDefinition();beanDefinition.setBeanClass(clssze);String id = null;id =element.getAttribute("name");if (id == null) {if (clssze ==MyExecutor.class) {id = "test_myExecutor";} else if (clssze ==MyEntity.class) {id ="test_myentity";} else {throw newIllegalStateException("MyBeanDefinitionParser.parse,未知的业务逻辑处理:class:" +element.getAttribute("class"));}}int counter = 2;while(parserContext.getRegistry().containsBeanDefinition(id)) {id = id +(counter++);}if (id != null &&id.length() > 0) {if(parserContext.getRegistry().containsBeanDefinition(id)) {throw newIllegalStateException("Duplicate spring bean id " + id);}parserContext.getRegistry().registerBeanDefinition(id,beanDefinition);}NamedNodeMap nnm =element.getAttributes();for (int i = 0; i <nnm.getLength(); i++) {Node node =nnm.item(i);String key =node.getLocalName();String value =node.getNodeValue();if(key.equals("entity")) {if(parserContext.getRegistry().containsBeanDefinition(value)) {beanDefinition.getPropertyValues().add(key,parserContext.getRegistry().getBeanDefinition(value));} else {beanDefinition.getPropertyValues().add(key,new RuntimeBeanReference(value));}} else {beanDefinition.getPropertyValues().add(key,value);}}return beanDefinition;}
}

这个类会在

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Elementroot, BeanDefinitionParserDelegate delegate)这个方法中入口执行

然后到org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(Elementelement, ParserContext parserContext);

最后找到对应的BeanDefinitionParser执行parse方法。至于放入BeanDefinitionParser的入口就在自定义的NamespaceHandler中init()方法中。

com/ruishenh/spring/config/MyEntity.java实体类:

package com.ruishenh.spring.config;import com.ruishenh.model.BaseModel;public classMyEntity extendsBaseModel{private int dbTypeID;private String dbTypeName;private String splitBy;private String sql;private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSplitBy() {return splitBy;}public void setSplitBy(StringsplitBy) {this.splitBy = splitBy;}public String getSql() {return sql;}public void setSql(String sql) {this.sql = sql;}public int getDbTypeID() {return dbTypeID;}public void setDbTypeID(int dbTypeID) {this.dbTypeID = dbTypeID;}public String getDbTypeName(){return dbTypeName;}public void setDbTypeName(StringdbTypeName) {this.dbTypeName = dbTypeName;}}

com/ruishenh/spring/config/MyExecutor.java实体类:

package com.ruishenh.spring.config;import com.ruishenh.model.BaseModel;public classMyExecutor  extends BaseModel{private String name;private int delay;private int interval;private String address;private MyEntity entity;public MyEntity getEntity() {return entity;}public void setEntity(MyEntity entity) {this.entity = entity;}public int getDelay() {return delay;}public void setDelay(int delay) {this.delay = delay;}public int getInterval() {return interval;}public void setInterval(int interval) {this.interval = interval;}public String getAddress() {return address;}public void setAddress(Stringaddress) {this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

测试类:

package com.ruishenh.spring.test;import org.springframework.context.support.FileSystemXmlApplicationContext;import com.ruishenh.spring.config.MyEntity;
import com.ruishenh.spring.config.MyExecutor;public classTest {public static void main(String[] args) {Stringconf = "classpath:spring/myTest.xml";FileSystemXmlApplicationContextac = newFileSystemXmlApplicationContext(conf);MyExecutorme = ac.getBean(MyExecutor.class);System.out.println(me.toString());MyEntity mye = ac.getBean(MyEntity.class);System.out.println(mye.toString());}
}

运行结果:

MyExecutor[name=myexecutor,delay=2000,interval=5000,address=127.0.0.1,entity=MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]]

MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]

spring 自定义标签 学习相关推荐

  1. spring 自定义标签 学习二

    在上篇中写的只支持写属性,不支持标签property的写法,但是如果有时候我们还想做成支持 property的用法,则可以在xsd中增加spring 自带的xsd引用 修改xsd文件如下: <? ...

  2. Spring自定义标签使用及原理

    最近大半年一直在看spring的源码,寻思着需要写点什么,也锻炼下自己文档编写的能力.本篇我们讲解spring自定义标签的使用及原理,分为以下小节进行讲解. 自定义标签的用途 自定义标签使用 自定义标 ...

  3. 【Spring学习】Spring自定义标签详细步骤

    目录标题 前言 一.自定义标签步骤 1.定义属性POJO 2.定义XSD文件描述组件内容 3.定义标签解析器 4.注册标签解析器 5.定义spring.handlers和spring.schemas文 ...

  4. dubbo源码学习(二) : spring 自定义标签

    做dubbo的配置时很容易发现,dubbo有一套自己的标签,提供给开发者配置,其实每一个标签对应着一个 实体,在容器启动的时候,dubbo会对所有的配置进行解析然后将解析后的内容设置到实体里,最终du ...

  5. jsp自定义标签学习

    简单的说明: 1,说明---jsp自定义标签: HelloWorld:jsp自定义标签的使用流程: QueryTag:带属性标签的定义以及连接数据库使用: IteratorTag:带标签体的标签定义以 ...

  6. spring 自定义标签的实现

    在我们进行Spring 框架开发中,估计用到最多的就是bean 标签吧,其实在Spring中像<mvc/><context/>这类标签以及在dubbo配置的标签都是属于自定义的 ...

  7. spring自定义标签实现

    http://mozhenghua.iteye.com/blog/1830842 spring中编写配置可以用两种方式: 普通的通过 <bean id="" class=&q ...

  8. JSP自定义标签学习笔记

    http://blog.csdn.net/liangbinny/article/details/6309893 本文是本人学习<JavaWeb学习>书籍所记下的学习笔记 一.概述 JSP ...

  9. return error怎么定义_这一次搞懂Spring自定义标签以及注解解析原理

    自定义标签解析原理 在上一篇分析默认标签解析时看到过这个类DefaultBeanDefinitionDocumentReader的方法parseBeanDefinitions:拉勾IT课小编为大家分解 ...

最新文章

  1. 比较某两个时间的时间戳相等
  2. 使用 Composer 安装 Laravel 框架
  3. PS教程第二十四课:魔法棒
  4. python清洗文本数据_02.数据预处理之清洗文本信息
  5. Mac电视投屏工具:Mirror for Any Device for Mac
  6. ReportViewer教程(15)-矩阵报表-6
  7. LINUX-iostat命令讲解
  8. Windows平台下编译FFmpeg
  9. 记录一个Lock和sychronized应用及双检锁
  10. ps读写ddr3里面的数据 zynq_ZYNQ应该如何让PS端的opencv程序读取到ddr中的图像数据...
  11. 一文读懂ssh,tomcat,LANP,LNMP,ftp,dns等常见的环境配置(运维工程师必看)
  12. python加法_python加法运算
  13. 基于Eclipse+Java+Swing+Mysql图书信息管理系统
  14. Java学习之【Object】
  15. Linux 上最好的 9 个免费视频编辑软件(2018) | Linux 中国
  16. IDEA Git 复制分支到新分支 提交到新分支
  17. 敏捷实践 | 浅谈测试金字塔
  18. python笛卡尔_Python 计算笛卡尔积
  19. Eventually Consistent(最终一致性)(转)
  20. 显示器分辨率一直跳_台式机的屏幕总是闪烁是怎么回事 怎么调电脑分辨率

热门文章

  1. 视频教程-ajax教程 在线视频培训教程(含课程源代码)-JavaScript
  2. 再议事理图谱(首届事理图谱研讨会参后感)
  3. vue垂死挣扎系列(一)——vue-cli快速搭建
  4. 黑群晖二合一已损毁_搬运 如何在黑群晖中重置损毁的储存池/储存空间
  5. 四川大学计算机学院2018复试,四川大学文学与新闻学院2018年研究生招生复试录取情况汇总.PDF...
  6. 笔记2--认识O(logN)的排序--快速排序
  7. 人民币成功“入篮”SDR,这意味着什么?
  8. Python爬虫学习笔记 (9) [初级] 小练习 爬取慕课网课程清单
  9. plant simulation 建模案例分析
  10. 阿里云服务器(Windows)磁盘空间不足时如何释放磁盘空间?