当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之IoC篇 - 解析自定义标签(XML 文件)

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  9. Spring 源码(4)在Spring配置文件中自定义标签如何实现?

    Spring 配置文件自定义标签的前置条件 在上一篇文章https://www.cnblogs.com/redwinter/p/16165274.html Spring BeanFactory的创建过 ...

随机推荐

  1. $key 的用法

    <?php $attr=array("a","b","c","d"); //$key,默认是主键值,$value, ...

  2. 关闭火车头dedecms发布模块自动关键词,解决火车头发布dedecms文章关键词过多问题

    用火车头发布dedecms文章时,经常会自动添加关键词,这些关键词默认有10个,数量过多,而且是随机提取的,乱七八糟的词都进去了,如下图所示: 这些关键词可能会成为se判断你作弊的依据,现在se也弱化 ...

  3. cocos2dx的内存管理机制

    首先我们必须说一下c++中变量的内存空间的分配问题,我们在c++中写一个类,可以在栈上分配内存空间也可以使用new在堆上分配内存空间,如果类对象是在栈上分配的内存空间,这个内存空间的管理就不是我们的事 ...

  4. 使用 systemd timer 备份数据库

    导读 主要的Linux发行版都改用systemd 来替代 System V启动方式,其中 systemd timer 能替代 crontab 计划任务的大部分功能.本文介绍了用systemd time ...

  5. 坚持不懈之linux haproxy的配置文件关键字查询手册

    1.关键词balance balance用于定义负载均衡的算法,可用于defaults.listen和backend中. balance使用方法如下: balance <algorithm> ...

  6. 【转】java反射详解

    转自:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的 ...

  7. 42.旋转数组的最小元素[Get min value of rotated array]

    [题目] 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5 ...

  8. Android简易数据存储之SharedPreferences

    Andorid提供了多种数据存储的方式,例如前面说到的“Android数据存储之SQLite的操作”是用于较复杂的数据存储.然而,如果有些简单的数据存储如果采用SQLite的方式的话会显得比较笨重.例 ...

  9. iOS 中contraints居中对齐的一点心得

    今天遇到一个布局问题,先看图 如何让第二个控件在第一个和第三个的竖直上的中间呢?contraint不能直接实现这样的效果.我们可以再添加一个控件,如图 这样之后,再把第二个控件和这个新添加的控件设置为 ...

  10. eclipse连接虚拟机

    1.启动eclipse 2.打开 "Help/Install New Software..." 3.打开Add…… 4.输入Name: Genymobile          Lo ...