本篇我們一起來看一下基于Extensible XML authoring 擴充Spring XML元素。這裡我總結了以下内容:
* Spring XML 擴充
* 編寫 XML Schema 檔案:定義 XML 結構
* 自定義 NamespaceHandler 實作:命名空間綁定
* 自定義 BeanDefinitionParser 實作:XML 元素與 BeanDefinition 解析
* 注冊 XML 擴充:命名空間與 XML Schema 映射
接下來我們就通過實際案例的方式一起實踐一下。代碼如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://time.eleven.org/schema/users"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://time.eleven.org/schema/users">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<!-- 定義 User 類型(複雜類型) -->
<xsd:complexType name="User">
<xsd:attribute name="id" type="xsd:long" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="city" type="City"/>
</xsd:complexType>
<!-- 定義 City 類型(簡單類型,枚舉) -->
<xsd:simpleType name="City">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="BEIJING"/>
<xsd:enumeration value="HANGZHOU"/>
<xsd:enumeration value="SHANGHAI"/>
</xsd:restriction>
</xsd:simpleType>
<!-- 定義 user 元素 -->
<xsd:element name="user" type="User"/>
</xsd:schema>
## 定義 namespace 與 NamespaceHandler 的映射
http\://time.eleven.org/schema/users=org.eleven.thinking.in.spring.configuration.metadata.UsersNamespaceHandler
http\://time.eleven.org/schema/users.xsd = org/eleven/thinking/in/spring/configuration/metadata/users.xsd
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eleven.thinking.in.spring.configuration.metadata;
import org.springframework.beans.factory.xml.NamespaceHandler;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* "users.xsd" {@link NamespaceHandler} 實作
*
* @author <a href="mailto:[email protected]">eleven</a>
* @since
*/
public class UsersNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// 将 "user" 元素注冊對應的 BeanDefinitionParser 實作
registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
}
}
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eleven.thinking.in.spring.configuration.metadata;
import org.eleven.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* "user" 元素的 {@link BeanDefinitionParser} 實作
*
* @author <a href="mailto:[email protected]">eleven</a>
* @since
*/
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return User.class;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
setPropertyValue("id", element, builder);
setPropertyValue("name", element, builder);
setPropertyValue("city", element, builder);
}
private void setPropertyValue(String attributeName, Element element, BeanDefinitionBuilder builder) {
String attributeValue = element.getAttribute(attributeName);
if (StringUtils.hasText(attributeValue)) {
builder.addPropertyValue(attributeName, attributeValue); // -> <property name="" value=""/>
}
}
}