当Spring拿到一个元素时首先要做的是根据命名空间进行解析,如果是默认的命名空间,则使用parseDefaultElement方法进行元素解析,否则使用parseCustom Element方法进行解析。

    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
} public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

自定义标签的使用

扩展Spring自定义标签配置大致需要以下几个步骤(前提是要把Spring的Core包加入项目中)。

  1. 创建一个需要扩展的组件。
  2. 定义一个XSD文件描述组件内容。
  3. 创建一个文件,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义。
  4. 创建一个Handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到Spring容器。
  5. 编写Spring.handlers和Spring.schemas文件。

现在我们就按照上面的步骤一步步地体验自定义标签的过程。

第一步:

public class TestBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestBean{" +
"name='" + name + '\'' +
'}';
}
}

第二步:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://code.alibabatech.com/schema/dubbo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://code.alibabatech.com/schema/dubbo"> <xsd:element name="custom" type="customType">
</xsd:element>
<xsd:complexType name="customType">
<xsd:attribute name="id" type="xsd:ID">
</xsd:attribute>
<xsd:attribute name="name" type="xsd:string">
</xsd:attribute>
</xsd:complexType> </xsd:schema>

第三步:

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element; public class TestCustomBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { String id = element.getAttribute("id");
String name = element.getAttribute("name"); RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(TestBean.class);
beanDefinition.getPropertyValues().addPropertyValue("name", name);
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); return beanDefinition;
}
}

第四步:

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class TestNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("custom", new TestCustomBeanDefinitionParser());
}
}

第五步:

spring.handlers:
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
spring.schemas:
http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

第六步:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:custom id="testCustom" name="this is a test custom tag" />
</beans> import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) {
String xml = "classpath:test.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { xml });
System.out.println(context.getBean("testCustom"));
}
} 上例输出为:
TestBean {name=this is a test custom tag}

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

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

    1. XML Schema 1.1 最简单的标签 一个最简单的标签,形式如: <bf:head-routing key="1" value="1" to= ...

  2. Spring——使用自定义标签

    文章内容参考了<Spring源码深度解析>一书.自己照着书中内容做了一遍,不懂的地方以及采坑的地方会在文中记录. 推荐一篇post,关于Spring配置文件的命名空间: https://w ...

  3. spring thymeleaf 自定义标签

    概述 thymeleaf2.1.5自定义标签及自定义属性案例,类似于JSP中的自定义JSTL标签 详细 代码下载:http://www.demodashi.com/demo/10495.html 一. ...

  4. Spring IoC 自定义标签解析

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  5. Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md

    写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...

  6. Spring 系列教程之自定义标签的解析

    Spring 系列教程之自定义标签的解析 在之前的章节中,我们提到了在 Spring 中存在默认标签与自定义标签两种,而在上一章节中我们分析了 Spring 中对默认标签的解析过程,相信大家一定已经有 ...

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

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

  8. Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签

    写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...

  9. spring整合freemarker 自定义标签

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

随机推荐

  1. POJ 2960 博弈论

    题目链接: http://poj.org/problem?id=2960 S-Nim Time Limit: 2000MS Memory Limit: 65536K 问题描述 Arthur and h ...

  2. no module named staticfiles

    原地址:http://blog.sina.com.cn/s/blog_77500e110100umms.html 今天想试一下django的Uploadify,找了个例子,运行时出错:myprojec ...

  3. Struts2注解 特别注意

    1 Struts2注解的作用 使用注解可以用来替换struts.xml配置文件!!! 2 导包 必须导入struts2-convention-plugin-2.3.15.jar包,它在struts2安 ...

  4. java基础(十七)集合(四)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...

  5. Oracle100w数据大表割接

    [现网问题] 最近在给咪咕做视频后台管理,移动那边希望页面上,码流字段可以支持1位小数,如8.0.自己查看数据库,发现码流字段是Number整型,也就是要换类型,打算直接换成varchar2.因为自己 ...

  6. Nodejs连接mysql的增、删、改、查操作

    一,创建数据库 Source Database : my_news_test SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- ...

  7. HDU6124

    Euler theorem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)T ...

  8. bootstrap-treeview的 简单使用

    理论:http://blog.csdn.net/babyxue/article/details/73835444 插依赖Bootstrap 和jQuery <link href="~/ ...

  9. hibernate 一对一 one to one的两种配置方式

    hibernate中one-to-one两种配置方式 标签: hibernateHibernateone-to-one 2013-02-19 17:44 11445人阅读 评论(1) 收藏 举报  分 ...

  10. 网站sql注入漏洞修复方案之metinfo 6.1.0系列

    近日,我们SINE安全对metinfo进行网站安全检测发现,metinfo米拓建站系统存在高危的sql注入漏洞,攻击者可以利用该漏洞对网站的代码进行sql注入攻击,伪造恶意的sql非法语句,对网站的数 ...