欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring源码之NamespaceHandler和NamespaceHandlerSupport

程序员文章站 2022-05-21 19:26:08
...

最近看分布式平台消息队列组件源码的时候,涉及到了使用继承自NamespaceHandlerSupport的类来向spring容器中注入bean定义解析器

NamespaceHandler

直接上NamespaceHandler代码:

public interface NamespaceHandler {
	/**
	 *	初始化向spring容器中注册bean定义解析器
	 */
    void init();
	
	/**
	 *	解析函数
	 */
    BeanDefinition parse(Element var1, ParserContext var2);

    BeanDefinitionHolder decorate(Node var1, BeanDefinitionHolder var2, ParserContext var3);
}

NamespaceHandlerSupport

NamespaceHandlerSupport则是NamespaceHandler的实现,但仍然是抽象类

首先它有如下变量:

private final Map<String, BeanDefinitionParser> parsers = new HashMap();
private final Map<String, BeanDefinitionDecorator> decorators = new HashMap();
private final Map<String, BeanDefinitionDecorator> attributeDecorators = new HashMap();

这三个HashMap中装的分别是:Bean定义解析器和装饰器

构造函数:

public NamespaceHandlerSupport() {}

实现父类parse函数:

public BeanDefinition parse(Element element, ParserContext parserContext) {
	//调用了本地的findParserForElement函数
	return this.findParserForElement(element, parserContext).parse(element, parserContext);
}

findParserForElement函数:

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
	/*
	 *	首先根据元素element获取其localName
	 */
	String localName = parserContext.getDelegate().getLocalName(element);
	/*
	 *	然后根据localName从map(parsers)中获取Bean定义解析器
	 */
	BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);
	if (parser == null) {
		/*
		 *	找不到解析器则提示
		 */
		parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
	}
	return parser;
}

实现父类decorate方法和上述类似,只不过是从decorators 和 attributeDecorators中查找:

	public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
		return this.findDecoratorForNode(node, parserContext).decorate(node, definition, parserContext);
	}

    private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) {
        BeanDefinitionDecorator decorator = null;
        /*
		 *	首先根据元素element获取其localName
	 	 */
        String localName = parserContext.getDelegate().getLocalName(node);
        /**
         *	判断node是Element还是Attr,再查找对应的decorator
         */
        if (node instanceof Element) {
            decorator = (BeanDefinitionDecorator)this.decorators.get(localName);
        } else if (node instanceof Attr) {
            decorator = (BeanDefinitionDecorator)this.attributeDecorators.get(localName);
        } else {
            parserContext.getReaderContext().fatal("Cannot decorate based on Nodes of type [" + node.getClass().getName() + "]", node);
        }

        if (decorator == null) {
            parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionDecorator for " + (node instanceof Element ? "element" : "attribute") + " [" + localName + "]", node);
        }

        return decorator;
    }

最后是三个注册方法,分别向spring容器中注册parser,decorator,本质上是放入HashMap中:

	protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
        this.parsers.put(elementName, parser);
    }

    protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) {
        this.decorators.put(elementName, dec);
    }

    protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec) {
        this.attributeDecorators.put(attrName, dec);
    }

使用

写一个类继承NamespaceHandlerSupport,实现init()方法:

public class MQNamespaceHandler extends NamespaceHandlerSupport{

	public void init() {
		registerBeanDefinitionParser("publisher", new PublisherBeanDefinitionParser());
		registerBeanDefinitionParser("subscriber", new SubscriberBeanDefinitionParser());
	}

}