某些情况下,为了给业务系统提供可配置化支持,我们一般会用原生态的方式去解析定义好的XML文件,然后转化为配置对象。这种方式对于简单、单一的配置文件,或者是XML配置格式固定的配置文件,还是比较容易处理的。但是对于一些复杂的、对可扩展性、灵活性要求比较高的场景,使用这种方式去验证、解析就会比较麻烦了。针对这种情况,Spring提供了对用户扩展Schema的支持,这样就可以使用Spring已有的验证、解析工具进行自定义标签的处理了。

  扩展Spring自定义标签配置还是比较简单的,大致需要以下几个步骤:

  1. 创建一个需要扩展的组件类
  2. 定义一个XSD文件,描述组件内容
  3. 创建一个类,实现BeanDefinitionParser接口,用来解析XSD文件中的各种定义以及组件定义
  4. 创建一个Handler类,并继承NamespaceHandlerSupport类,目的是将组件注册到Spring容器
  5. 编写spring.schemas和spring.handlers文件分别指定parser与handler,spring默认会通过这两个文件找到BeanDefinitionParser与NamespaceHandlerSupport

下边通过一个简单的示例来展示一下如何创建一个自定义的标签。

  1. 创建一个普通的POJO类

    public class User {
    private String userName;
    private String email;
    public String getUserName() {
    return userName;
    }
    public void setUserName(String userName) {
    this.userName = userName;
    }
    public String getEmail() {
    return email;
    }
    public void setEmail(String email) {
    this.email = email;
    }
    }
  2. 定义一个XSD文件,用来描述组件内容
    <?xml version="1.0" encoding="UTF-8"?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/schema/user" xmlns:tns="http://www.example.org/schema/user" elementFormDefault="qualified">
    <element name="user">
    <complexType>
    <attribute name="id" type="string"></attribute>
    <attribute name="userName" type="string"></attribute>
    <attribute name="email" type="string"></attribute>
    </complexType>
    </element>
    </schema>

    将XSD文件放在src/main/resources/META-INF下,名称为spring-test.xsd

  3. 创建一个类,实现BeanDefinitionParser接口,用来解析XSD文件中的各种定义和组件定义
    public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{
    
        @Override
    protected Class<?> getBeanClass(Element element){
    return User.class;
    } @Override
    protected void doParse(Element element, BeanDefinitionBuilder bean){
    String userName = element.getAttribute("userName");
    String email = element.getAttribute("email");
    if(StringUtils.hasText(userName)){
    bean.addPropertyValue("userName", userName);
    }
    if(StringUtils.hasText(email)){
    bean.addPropertyValue("email", email);
    }
    }
    }
  4. 创建一个Handler类,并继承NamesapceHandlerSupport,目的是将组件注册到Spring容器
    public class MyNamespaceHandlerSupport extends NamespaceHandlerSupport{
    @Override
    public void init() {
    registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
    }
    }
  5. 目前spring还无法加载我们这些自定义的东西,还需要让spring能够找到并加载我们自定义的东西,这个时候就要用到spring.handlers和spring.schemas文件,因为spring会默认查找src/main/resources/META-INF目录下的这两个文件,来检查是否有用户自定义的标签。
    • spring.schemas

      http\://www.example.org/schema/user.xsd=META-INF/spring-test.xsd
    • spring.handlers
      http\://www.example.org/schema/user=chapter04.MyNamespaceHandlerSupport

下边测试一下我们自定义的标签

  1. 创建测试的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:myname="http://www.example.org/schema/user"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.example.org/schema/user http://www.example.org/schema/user.xsd">
    <myname:user id="testbean" userName="aaa" email="bbb" />
    </beans>

    这里的过程是,注意第四行“xmlns:myname”,当遇到myname开头的标签时,就会通过xmlns:myname="http://www.example.org/schema/user"找到该标签的命名空间为"http://www.example.org/schema/user",然后通过spring.handlers找到对应的该命名空间的handler为chapter04.MyNamespaceHandlerSupport,然后将名字为user的子标签交由UserBeanDefinitionParser对象进行处理。当需要对xml的元素进行验证时,通过第七行可以找到命名空间对应的xsd的名称http://www.example.org/schema/user.xsd,然后通过spring.schemas找到实际的xsd文件对应的位置META-INF/spring-test.xsd,通过spring-test.xsd对元素进行校验。

  2. 创建测试类
    public class Test {
    public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext("beanFactoryTest.xml");
    User user = (User)ac.getBean("testbean");
    System.out.println(user.getUserName() + "," + user.getEmail());
    }
    }

spring中的自定义标签的更多相关文章

  1. 在jsp页面中使用自定义标签

    在某些场景中,自定义标签可封装大量代码,使页面变得更简洁,标签也可以很方便地在不同页面中实现通用而不必去粘贴大量的js代码.现在把最近做的一个自定义标签在这里总结一下.首先总结一下关于自定义标签的一些 ...

  2. springbank 开发日志 Spring启动过程中对自定义标签的处理

    这篇随笔的许多知识来源于:http://www.importnew.com/19391.html 之所以会去看这些东东,主要是希望能够模仿spring mvc的处理流程,做出一套合理的交易处理流程. ...

  3. Spring源码分析(九)解析默认标签中的自定义标签元素

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 到这里我们已经完成了分析默认标签的解析与提取过程,或许涉及的内容太多,我 ...

  4. spring源码-自定义标签-4

    一.自定义标签,自定义标签在使用上面相对来说非常常见了,这个也算是spring对于容器的拓展.通过自定义标签的方式可以创造出很多新的配置方式,并且交给容器直接管理,不需要人工太多的关注.这也是spri ...

  5. 在django中使用自定义标签实现分页功能

    效果演示: github地址:https://github.com/mncu/django_projects/tree/master/django_projects/pagination_test 本 ...

  6. javaWeb 在jsp中 使用自定义标签输出访问者IP

    1.java类,使用简单标签,jsp2.0规范, 继承 SimpleTagSupport public class ViewIpSimpleTag extends SimpleTagSupport { ...

  7. spring整合freemarker 自定义标签

    1.自定义标签实现 TemplateDirectiveModel 接口 2.spring 配置,注意标红的两行 <bean id="freemarkerConfig" cla ...

  8. Spring中的p标签(转)good

    Spring的p标签是基于XML Schema的配置方式,目的是为了简化配置方式. 在XML文件头部添加xmlns:p="http://www.springframework.org/sch ...

  9. spring中增加自定义配置支持

    spring.schemas 在使用spring时,我们会首先编写spring的配置文件,在配置文件中,我们除了使用基本的命名空间http://www.springframework.org/sche ...

随机推荐

  1. 面向接口编程实现不改代码实现Redis单机/集群之间的切换

    开发中一般使用Redis单机,线上使用Redis集群,因此需要实现单机和集群之间的灵活切换 pom配置: <!-- Redis客户端 --> <dependency> < ...

  2. 【转】深入浅出:Linux设备驱动之字符设备驱动

    深入浅出:Linux设备驱动之字符设备驱动 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据 ...

  3. Tomcat Java.OutOfMemoryError : PermGen Space异常

    背景:前些日子更新公司多年前一个旧平台发布到Tomcat上之后,频繁收到网站许多模块无法正常使用的反汇. 测试过程中发现平台发布一段时间后,访问相关网页出现如下500页面 解决方案:PermGen s ...

  4. 兼容性问题--HTML+CSS

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Consolas; color: #a5b2b9 } span.Apple-tab-span ...

  5. Linux命令用法

    1.cut http://www.cnblogs.com/dong008259/archive/2011/12/09/2282679.html 2.sed http://www.cnblogs.com ...

  6. 前端菜鸟学习之DOM事件处理

    一.事件处理程序 1.DOM0级事件处理程序:就是将一个函数赋值给一个事件处理程序属性,至今仍为现代所有浏览器所支持,主要得益于其跨浏览器的优势,要使用DOM0级事件 首先要得到操作对象的引用,具体实 ...

  7. Longest Common Substring(最长公共子序列)

    Longest Common Substring Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...

  8. 解决mysql启动失败报1067错误

    最近做项目使用 mysql 数据库 ,因为卸载了鲁大师造成了数据库文件缺失.重装mysql数据库后启动出现了1067错误,详情如下 在网上查了错误原因,将my.ini文件下的默认搜索引擎换成了 myi ...

  9. Magicodes.Admin.Core开源框架总体介绍

    框架说明 Magicodes.Admin.Core框架在ABP以及ASP.NET ZERO的基础上进行了封装和完善,目前基于.NET Core 2.0+(Framework版本),由于部分组件在.NE ...

  10. word中表格第一列序号的设置

    表格中序号问题 1.新建一个表格.第一列选择编号后,编号后有tab,如下图 2.选中表格的编号,点击新建列表样式, 3.将编号后的字符改成nothing,在将单元格改成居中即可 4.在将单元格改成居中 ...