spring的自定义schema

1.项目结构

spring的自定义schema_第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);
        }
    }

    org.springframework.beans.factory.xml.BeanDefinitionParserDelegate

    进行自定义解析

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));
	}

     org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver

     返回自己的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));
	}

    org.springframework.beans.factory.xml.NamespaceHandlerSupport

    通过该方法找到对应自定义的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方法里的那样。

你可能感兴趣的:(spring,dubbo,xml)