1.项目结构
2.代码
package com.alibaba.dubbo.demo.xml;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element;
public class MyBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private Class> beanClass;
public MyBeanDefinitionParser(Class> beanClass) {
this.beanClass = beanClass;
}
@SuppressWarnings("rawtypes")
protected Class getBeanClass(Element element) {
return beanClass;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String orderId = element.getAttribute("orderId");
bean.addPropertyValue("orderId", orderId);
String userId = element.getAttribute("userId");
bean.addPropertyValue("userId", Integer.valueOf(userId));
}
}
package com.alibaba.dubbo.demo.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("or", new MyBeanDefinitionParser(
Order.class));
}
}
package com.alibaba.dubbo.demo.xml;
public class Order {
private Integer orderId;
private String userId;
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", userId=" + userId + "]";
}
}
package com.alibaba.dubbo.demo.xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class OrderXsdTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"xml_applicationContex.xml");
Order order1 = (Order) ctx.getBean("order1");
System.out.println(order1);
}
}
3.配置文件
order.xsd
订单ID
用户ID
spring.handlers
http\://www.myschema.com/schema/order=com.alibaba.dubbo.demo.xml.MyNamespaceHandler
spring.schemas
http\://www.myschema.com/schema/order.xsd=META-INF/order.xsd
xml_applicationContex.xml
4.代码分析
执行main方法加载spring,当解析xml的节点的时候会做一个判断
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"xml_applicationContex.xml");
Order order1 = (Order) ctx.getBean("order1");
System.out.println(order1);
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader
在解析xml_applicationContex.xml的时候触发该方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//判断根节点是否是默认的命名空间http://www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
//获取所有的子节点
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;
//查看该子节点的命名空间
String namespaceUri = ele.getNamespaceURI();
//如果是默认的命名空间 那么就走默认的解析方法
if (delegate.isDefaultNamespace(namespaceUri)) {
parseDefaultElement(ele, delegate);
}
//如果不是默认的命名空间 那么就走自定义的解析方法
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
进行自定义解析
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//获取自定义的schema的命名空间
String namespaceUri = ele.getNamespaceURI();
//获取自定义的namespace类
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));
}
返回自己的handler类
public NamespaceHandler resolve(String namespaceUri) {
//获取所有spring.handlers文件里的内容封装成一个map
Map handlerMappings = getHandlerMappings();
//通过命名空间获取namespace的类路径(spring.handlers配置的)
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
//实例化自己的handler
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//调用自己的handler的init方法
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "] not found", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" +
namespaceUri + "]: problem with handler class file or dependent class", err);
}
}
}
com.alibaba.dubbo.demo.xml.MyNamespaceHandler
调用自己的handler类的init方法
@Override
public void init() {
registerBeanDefinitionParser("or", new MyBeanDefinitionParser(
Order.class));
}
通过该方法找到对应自定义的schema的类
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
//获取自定义的解析类
BeanDefinitionParser parser = (BeanDefinitionParser) this.parsers.get(element.getLocalName());
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + element.getLocalName() + "]", element);
}
return parser;
}
com.alibaba.dubbo.demo.xml.MyBeanDefinitionParser
接着就调用自己的doParse方法
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String orderId = element.getAttribute("orderId");
bean.addPropertyValue("orderId", orderId);
String userId = element.getAttribute("userId");
bean.addPropertyValue("userId", Integer.valueOf(userId));
}
接着就是把该类注入到了spring的容器里,可以通过getbean获取到该对象了
就行main方法里的那样。