基于schema的spring xml namespace扩展
来源:互联网 发布:excel 数据分析 知乎 编辑:程序博客网 时间:2024/04/30 15:40
基于schema的spring xml namespace扩展
Spring2.0后,可以基于spring的schema来扩展xml format,加入自定义的schema元素。
步骤如下:
1.定义xml schema描述个性化的元素信息
2.编写自定义的NamespaceHandler
3.编写一个或多个BeanDefinitionParser来解析Xml元素
4.注册成为spring的artifacts
demo可以参考http://static.springsource.org/spring/docs/2.5.x/reference/extensible-xml.html
说明:
spring.schema定义uri对应的xsd的位置,基于classpath
spring.handlers定义uri对应的解析类
spring.schema基本思路:
1.spring在解析XML配置文件时,通过DelegatingEntityResolver来解析xml中的元素信息,包括header信息.
初始化:
public DelegatingEntityResolver(ClassLoaderclassLoader) {
this.dtdResolver= new BeansDtdResolver();
this.schemaResolver= new PluggableSchemaResolver(classLoader);
}
调用PluggableSchemaResolver:
public InputSource resolveEntity(StringpublicId, String systemId) throws SAXException, IOException {
if(systemId != null) {
if(systemId.endsWith(DTD_SUFFIX)) {
returnthis.dtdResolver.resolveEntity(publicId, systemId);
}
elseif (systemId.endsWith(XSD_SUFFIX)) {
returnthis.schemaResolver.resolveEntity(publicId, systemId);
}
}
returnnull;
}
2.PluggableSchemaResolver来解析指定的资源
public static final StringDEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";
调用工具类加载资源信息
private Map<String, String>getSchemaMappings() {
if(this.schemaMappings == null) {
synchronized(this) {
if(this.schemaMappings == null) {
if(logger.isDebugEnabled()) {
logger.debug("Loadingschema mappings from [" + this.schemaMappingsLocation + "]");
}
try{
Propertiesmappings =
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation,this.classLoader);
if(logger.isDebugEnabled()) {
logger.debug("Loadedschema mappings: " + mappings);
}
Map<String,String> schemaMappings = new ConcurrentHashMap<String, String>();
CollectionUtils.mergePropertiesIntoMap(mappings,schemaMappings);
this.schemaMappings= schemaMappings;
}
catch(IOException ex) {
thrownew IllegalStateException(
"Unableto load schema mappings from location [" + this.schemaMappingsLocation +"]", ex);
}
}
}
}
returnthis.schemaMappings;
}
3.PropertiesLoaderUtils
根据classloader加载所有的资源,注意因为不同的jar包的资源名字可能相同,所以使用的是classloader的getResources接口:
public static PropertiesloadAllProperties(String resourceName, ClassLoader classLoader) throwsIOException {
Assert.notNull(resourceName,"Resource name must not be null");
ClassLoaderclToUse = classLoader;
if(clToUse == null) {
clToUse= ClassUtils.getDefaultClassLoader();
}
Propertiesproperties = new Properties();
Enumerationurls = clToUse.getResources(resourceName);
while(urls.hasMoreElements()) {
URLurl = (URL) urls.nextElement();
InputStreamis = null;
try{
URLConnectioncon = url.openConnection();
con.setUseCaches(false);
is= con.getInputStream();
properties.load(is);
}
finally{
if(is != null) {
is.close();
}
}
}
returnproperties;
}
4.根据xml中的自定义元素根据指定的xsd类型信息来验证。
public InputSource resolveEntity(StringpublicId, String systemId) throws IOException {
if(logger.isTraceEnabled()) {
logger.trace("Tryingto resolve XML entity with public id [" + publicId +
"]and system id [" + systemId + "]");
}
if(systemId != null) {
StringresourceLocation = getSchemaMappings().get(systemId);
if(resourceLocation != null) {
Resourceresource = new ClassPathResource(resourceLocation, this.classLoader);
try{
InputSourcesource = new InputSource(resource.getInputStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
if(logger.isDebugEnabled()) {
logger.debug("FoundXML schema [" + systemId + "] in classpath: " +resourceLocation);
}
returnsource;
}
catch(FileNotFoundException ex) {
if(logger.isDebugEnabled()) {
logger.debug("Couldn'tfind XML schema [" + systemId + "]: " + resource, ex);
}
}
}
}
returnnull;
}
spring.handles基本思路:
1.spring 在解析xml元素后,要通过XmlBeanDefinitionReader转换成Bean Definition信息。
1.1将前面提到的DelegatingEntityResolver(PluggableSchemaResolver)放到DocumentLoader中
1.2注册bean definition到Dom中
viewplain
protected int doLoadBeanDefinitions(InputSourceinputSource, Resource resource)
throwsBeanDefinitionStoreException {
try {
intvalidationMode = getValidationModeForResource(resource);
Documentdoc = this.documentLoader.loadDocument(
inputSource,getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
returnregisterBeanDefinitions(doc, resource);
}
catch(BeanDefinitionStoreException ex) {
throw ex;
}
catch(SAXParseException ex) {
throw newXmlBeanDefinitionStoreException(resource.getDescription(),
"Line" + ex.getLineNumber() + " in XML document from " + resource +" is invalid", ex);
}
catch(SAXException ex) {
throw newXmlBeanDefinitionStoreException(resource.getDescription(),
"XMLdocument from " + resource + " is invalid", ex);
}
catch(ParserConfigurationException ex) {
throw newBeanDefinitionStoreException(resource.getDescription(),
"Parserconfiguration exception parsing XML from " + resource, ex);
}
catch(IOException ex) {
throw newBeanDefinitionStoreException(resource.getDescription(),
"IOExceptionparsing XML document from " + resource, ex);
}
catch(Throwable ex) {
throw newBeanDefinitionStoreException(resource.getDescription(),
"Unexpectedexception parsing XML document from " + resource, ex);
}
}
2.调用DefaultDocumentLoader,将前面提到的DelegatingEntityResolver(PluggableSchemaResolver)放到DocumentLoader中
protected DocumentBuilder createDocumentBuilder(
DocumentBuilderFactoryfactory, EntityResolver entityResolver, ErrorHandler errorHandler)
throwsParserConfigurationException {
DocumentBuilderdocBuilder = factory.newDocumentBuilder();
if(entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if(errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
returndocBuilder;
}
3. 注册beandefinition到Dom中,在遍历xml元素,如果是子定义的元素,调用spring.handlers定义的解析类来解析
public int registerBeanDefinitions(Document doc, Resourceresource) throws BeanDefinitionStoreException {
// Readdocument based on new BeanDefinitionDocumentReader SPI.
BeanDefinitionDocumentReaderdocumentReader = createBeanDefinitionDocumentReader();
intcountBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc,createReaderContext(resource));
returngetRegistry().getBeanDefinitionCount() - countBefore;
}
protectedXmlReaderContext createReaderContext(Resource resource) {
if(this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver= createDefaultNamespaceHandlerResolver();
}
return newXmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor,this, this.namespaceHandlerResolver);
}
4.剩下就是ApplicationContext根据解析后的Bean Definition来构造Bean的实例了。
- 基于schema的spring xml namespace扩展
- 基于schema的spring xml namespace扩展
- 基于Spring的扩展Schema配置
- Spring : 基于XML Schema 的配置 (二)
- xml的Schema扩展
- 扩展spring 的 xml schema,实现自己的标签
- Spring的XML文件的Schema扩展点PluggableSchemaResolver
- XML:Schema(namespace)
- xml schema namespace相关
- spring 基于XML Schema的简化配置方式
- Spring : 基于XML Schema的配置(一)
- Spring-----11、基于XML Schema的简化配置方式
- Spring : 基于XML Schema的配置(一)(转载)
- spring学习之---基于XML Schema的简化配置方法
- Unable to locate Spring NamespaceHandler for XML schema namespace
- Unable to locate Spring NamespaceHandler for XML schema namespace异常
- Unable to locate Spring NamespaceHandler for XML schema namespace
- Unable to locate Spring NamespaceHandler for XML schema namespace
- SSH是什么东西
- Flex 自定义Alert-给alert添加按钮
- csdn积分规则
- XML的SAX解析器
- 外部程序通过COM启动AutoCAD时RPC_E_CALL_REJECTED的问题解决办法
- 基于schema的spring xml namespace扩展
- Oracle学习笔记-0002
- extern "C"的用法解析
- C# DLL库自动注册的两种方法(调用Regsvr32法、调用DllRegisterServer函数法)
- CardLayout卡片布局(Firsh、Next、Previous、Last功能演示)
- do...while(0)的妙用
- 整理cortex-m3开发相关
- php中time()和mktime()方法的区别
- mysql基本命令