今天看了一下分布式服务框架的那本书,于是里面提到了spring schema的自定义,于是去简单的了解了一下
参考资源:spring schema扩展: http://www.yihaomen.com/article/java/438.htm
schema定义:http://www.w3school.com.cn/schema/schema_schema.asp
spring schema扩展:http://blog.csdn.net/cutesource/article/details/5864562
spring schema相关字段含义:http://luyuanliang.iteye.com/blog/2154805
在使用分布式服务框架的时候,经常看到有这样的使用:
<dubbo:service interface="com.unj.dubbotest.provider.DemoService" ref="demoService" />
在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准Bean来配置,但配置较为复杂或者需要更多丰富控制的时候,
会显得非常笨拙。一般的做法会用原生态的方式去解析定义好的xml文件,然后转化为配置对象,这种方式当然可以解决所有问题,但实现起来比较繁琐,
特别是是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。Spring提供了可扩展Schema的支持,这是一个不错的折中方案,完成一个自定义
配置一般需要以下步骤:
- 设计配置属性和JavaBean
- 编写XSD文件
- 编写NamespaceHandler和BeanDefinitionParser完成解析工作
- 编写spring.handlers和spring.schemas串联起所有部件
- 在Bean文件中应用
1、设置配置属性
package com.springwork.xml; public class People { private String name; private int age; private String id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getId() { return id; } public void setId(String id) { this.id = id; } }
2、编写XSD文件
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.yihaomen.com/schema/people" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.yihaomen.com/schema/people" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans" /> <xsd:element name="people"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> //复合元素之上以某个复合元素为基础,然后添加一些元素,具体的解释看http://www.w3school.com.cn/schema/schema_complex.asp; <xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="age" type="xsd:int" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
3、编写NamespaceHandler和BeanDefinitionParser完成解析工作
package com.springwork.xml; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class MyNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser()); } }
package com.springwork.xml; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return People.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { String name = element.getAttribute("name"); String age = element.getAttribute("age"); String id = element.getAttribute("id"); if (StringUtils.hasText(id)) { bean.addPropertyValue("id", id); } if (StringUtils.hasText(name)) { bean.addPropertyValue("name", name); } if (StringUtils.hasText(age)) { bean.addPropertyValue("age", Integer.valueOf(age)); } } }
4、编写spring.handlers和spring.schemas串联起所有部件,该文件位于src/META-INF下
http\://www.yihaomen.com/schema/people=com.springwork.xml.MyNamespaceHandler
http\://www.yihaomen.com/schema/people.xsd=com/springwork/xml/people.xsd
5、在Bean文件中应用
将刚才的项目打包为jar,新建项目,导入该jar。编写spring配置文件
<?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:comtest="http://www.yihaomen.com/schema/people" //和spring.handlers先配置的连接一样 xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.yihaomen.com/schema/people http://www.yihaomen.com/schema/people.xsd "> <comtest:people id="cutesource" name="一号门" age="1024"/> </beans>
6、测试程序
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.springwork.xml.People; public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:/config/application.xml"); People p = (People) ctx.getBean("cutesource"); System.out.println(p.getId()); System.out.println(p.getName()); System.out.println(p.getAge()); } }
扩展:applicationContext 中 xmlns 与 xsi:schemaLocation 含意
xmlns是XML Namespaces的缩写,中文名称是XML(标准通用标记语言的子集)命名空间。 如上图所示"dog",在有可能产生命名冲突的场合,通过自定义命名空间来解决冲突。
schemaLocation
schemaLocation 属性用来引用(schema)模式文档,解析器可以在需要的情况下使用这个文档对 XML 实例文档进行校验。它的值(URI)是成对出现的,第一个值表示命名空间,
第二个值则表示描述该命名空间的模式文档的具体位置,两个值之间以空格分隔。当然,在必要情况下,可以为 schemaLocation 属性指派多个这样的值对。 如上图所示。
从上图可以看到,配置是两个URL地址,在不连网络的情况下,或者URL不是真实存在的场合,也可以进行加载,这是因为在META-INF下有两个配置文件。
通过映射读取本地信息。如下图所示。
第一个值表示命名空间,对应的文件是spring.handlers, 告诉spring用哪个类进行解析处理。 第二个值则表示描述该命名空间的模式文档的具体位置
关于配置示例图中:cat的映射关系: