某些情况下,为了给业务系统提供可配置化支持,我们一般会用原生态的方式去解析定义好的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. Java这些冷知识你知道吗?

    1)jvm有很多种,其实jvm是一个标准,sun做的那个叫hotspot,作者就是后来v8的作者lars bak,其他公司也做过jvm,其中做得比较好的有bea的jrockit,其他的包括ibm的r9 ...

  2. C#基本功之泛型

    一.没有泛型之前 在没有泛型之前,我们是怎么处理不同类型的相同操作的: 示例1 //下面是一个处理string类型的集合类型 public class MyStringList { string[] ...

  3. 3分钟利用TurnipBit制作电子时钟

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 TurnipBit(www.turnipbit.com)是一个面向青少年的开发板 ...

  4. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  5. awake()和start()还有update(),fixedupdate()的差别

    1.首先看一下untiy官方对awake()和start()的定义 awake()和start()函数会在脚本加载后自动调用,awake()会先被调用,即使脚本未被调用.最好用来设置脚本之间的引用和初 ...

  6. bug:论用例健壮性的重要

    最近出了2个类似问题,此处写下,以作为警醒 问题1: 背景:电商类网站,为了增加用户回流,增加用户购买力度,做了一个和用户等级相关活动 需求:用户等级为g0 -g5,现在有一批代金券有等级领取限制.用 ...

  7. angular内置provider之$compileProvider

    一.方法概览 directive(name, directiveFactory) component(name, options) aHrefSanitizationWhitelist([regexp ...

  8. IE10和IE11中滑动条遮挡页面问题

    今天在开发的过程中前端项目,在小设备上会出现滑动条,这本没什么,在其他浏览器上都很正常,但是在IE10和IE11上出现了问题,发现侧边滑动条挡住了一部分页面的内容,因为侧边有要操作的按钮,这就是一个很 ...

  9. 2301: [HAOI2011]Problem b ( 分块+莫比乌斯反演+容斥)

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 6015  Solved: 2741[Submit] ...

  10. JsDoc脚本注释文档生成

    使用jsDoc可使用特定注释,将注释的内容生成文档,可用于生成脚本库的API文档 jsdoc 文档:   http://usejsdoc.org/