NameSpace初探
和C++,C#等高级语言一样,XML同样面临大量文件放在一起的时候变量重名的问题,所以要用namespace把名字相同意义不同的变量隔离开。以下是一个简单的XML文档:
<root>
<child id = ‘0’>
hello world
</child>
<child id='1'>
one
</child>
</root>
这个例子里面没有namespace,下面是一段豆瓣API返回的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="<a href="http://www.w3.org/2005/Atom" xmlns:db="<a href="http://www.douban.com/xmlns/" xmlns:gd="<a href="http://schemas.google.com/g/2005" xmlns:opensearch="<a href="http://a9.com/-/spec/opensearchrss/1.0/" >
<id>http://api.douban.com/event/10069638</id>
<title>Debugging the Web </title>
<category scheme="<a href="http://www.douban.com/2007#kind" term="<a href="http://www.douban.com/2007#event.salon"/>
<author>
<link href="<a href="http://api.douban.com/people/1057620" />
<link href="<a href="http://www.douban.com/people/aka/"/>
<link href="<a href="http://t.douban.com/icon/u1057620-16.jpg"/>
name>胖胖的大头鱼</name>
<uri>http://api.douban.com/people/1057620</uri>
</author>
<db:attribute name="invite_only">no</db:attribute>
1、这里<entry xmlns="http://www.w3.org/2005/Atom" ,xmlns就是xml namespace的意思。
2、xmlns:db="http://www.douban.com/xmlns/" ,结合<db:attribute name="invite_only">no</db:attribute>这句话,可以理解了,db是一个namespace的简称,方便写在元素的名字前面,这样<db:attribute> 和 <attribute>, <gd:attribute>就不一样了。这种简称可以在一个文档里面区别变量,但是对大量的文档还是不行,所以namespace还有一个全称,就是这里的http://www.douban.com/xmlns/。这个全称其实写什么内容都行,对XML Parser来说都是当做字符串来处理的,但一来想名字比较麻烦,二来可以顺道做个广告,所以大家一般都用的网址。Parse的时候Parser根据全称来区别变量,所以就算两个文档中都有<db:attribute>,只要全称不一样,都没有问题。
3、但那个http://www.w3.org/2005/Atom到底是个啥啊,连个简称都没有。他的简称就是””,空串。这东西被称为default namespace,那些看上去没有前缀的都是在这个namespace下的。所以那个<author>不是裸的啊,人家其实是 <”http://www.w3.org/2005/Atom” : author> 所以裸的程序当然是解析不了的了。
为何要引入SpringExt
详见:http://www.openwebx.org/docs/springext.html
赋予了scheme组件化的功能,既能主拓展,又可以被拓展
SpringExt原理
运用了XML Schema中的<xsd:any>定义,<xsd:any>定义只关心namespace,不关心element的名称,自然可以接受未知的 element,前提是namespace必须一致。看下面例子:
<xsd:element name="resource" type="ResourceLoadingServiceResourceType">
<xsd:complexType name="ResourceLoadingServiceResourceType">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:any namespace="<a href="http://www.alibaba.com/schema/services/resource-loading/loaders" />
</xsd:choice>
<xsd:attribute name="pattern" type="xsd:string" use="required" />
</xsd:complexType>
定义了schema的拓展,但是spring还是无法解析,这时候需要提供对应的parses:
test=com.alibaba.parseTest
最后spring是如何把这一系列的规则组织起来的呢?
SpringExt如何使用
拓展点
1、定义:Webx3框架中,允许使用者对命名空间进行拓展,这些可以拓展的空间叫做拓展点,在使用拓展功能前需要首先需要配置拓展点
2、配置文件位置:位于classpath的META-INF的spring-configuration-points文件中:
services=http://www.alibaba.com/schema/services; defaultElement=service
services/data-resolver/factories=http://www.alibaba.com/schema/services/data-resolver/factories; defaultElement=factory; nsPrefix=dr-factories
其中包含了拓展点名称、命名空间URL、默认元素和命名空间前缀
捐献
1、定义:有了拓展点,就可以在该拓展点上进行拓展了,我们称为捐献
2、组成成分:包含一份XSD文件和一个NameSpace的解析类
3、配置文件位置:
XSD文件定义在classpath的"{configurationName}/{contributionName}.xsd"里面;而解析类定义在"{configurationName}.bean-defenition-parses"里面("/"由"*"代替),如下图:
//捐献的名称和解析类
turbine-rundata-resolver=com.alibaba.citrus.turbine.dataresolver.impl.TurbineRunDataResolverFactory$DefinitionParser
parameter-resolver=com.alibaba.citrus.turbine.dataresolver.impl.ParameterResolverFactory$DefinitionParser
form-resolver=com.alibaba.citrus.turbine.dataresolver.impl.FormResolverFactory$DefinitionParser
自己实现一个Schema
1、编写bean
public class Karry {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void execute() {
System.out.println("Hello "+name);
}
}
2、创建META-INF文件夹,并添加services.bean-defenition-parses文件
Karry = MyParse
3、创建解析类MyParse
public class MyPrase extends AbstractNamedBeanDefinitionParser<Karry> {
//当不能再ID的时候,以此作为beanId
@Override
protected String getDefaultName() {
// TODO Auto-generated method stub
return "Karry";
}
//将name标签解析为bean属性
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
SpringExtUtil.attributesToProperties(element, builder, "name");
}
}
4、在META-INF下增加Karry.xsd文件
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="<a href="http://www.w3.org/2001/XMLSchema" targetNamespace="<a href="http://www.example.org/Karry" xmlns:tns="<a href="http://www.example.org/Karry" elementFormDefault="qualified">
<xsd:element name="Karry">
<xsd:complexType >
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
5、在Spring配置文件中增加该Karry Bean
<?xml version="1.0" encoding="UTF-8" ?>
<beans:beans xmlns:xsi="<a href=" xmlns:services="<a href="http://www.alibaba.com/schema/services" xmlns:beans="<a href="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.alibaba.com/schema/services http://localhost:8080/schema/services.xsd
http://www.springframework.org/schema/beans http://localhost:8080/schema/www.springframework.org/schema/beans/spring-beans.xsd
">
<services:Karry name="chenshuai" />
</beans:beans>
6、增加测试类
public class TestSpringExt {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ctx = new XmlApplicationContext(new ClassPathResource("MySpringExt.xml"));
Karry res = (Karry) ctx.getBean("Karry");
res.execute();
}
}