在Spring的XML文件中通过命名空间配置的标签是怎么解析的?
其实在spring中把解析标签的类都都放在了相应的META-INF目录下的spring.handlers的文件中,比如mvc的命名空间解析设置在spring-webmvc-3.2.5.RELEASE.jar包下META-INF/spring.handlers的文件中。
这说明处理MVC这个命名空间的配置需要使用MvcNamespaceHandler(在其内部将mvc:annotation-driven交给AnnotationDrivenBeanDefinitionParser),源码如下:
解析配置的接口是org.springframework.beans.factory.xml.NamespaceHandler,它的实现结构如下:
在这个interface里定义了三个方法:init,parse,和decorate。init方法用来初始化自己;parse用来将配置的标签转化成spring所需要的BeanDefinition;decorate是装饰的意思,这个方法的作用是对所在的BeanDefinition进行一些修改,用的比较少。
public interface NamespaceHandler {
void init();
BeanDefinition parse(Element element, ParserContext parserContext);
BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}
NamespaceHandler的主要实现类有三个,NamespaceHandlerSupport,SimpleConstructorNamespaceHandler,SimplePropertyNamespaceHandler。NamespaceHandlerSupport就是这个接口的默认实现,一般的XXXNamespaceHandler都实现自这个类,这里只简单的介绍一下NamespaceHandlerSupport。
从源码中可以看出在NamespaceHandlerSupport中并没有做具体的解析工作,而是定义了三个解析器,MvcNamespaceHandler将解析的标签注册到NamespaceHandlerSupport上,通过委托给该元素注册的bean来解析所提供的元素。
public abstract class NamespaceHandlerSupport implements NamespaceHandler {
private final Map<String, BeanDefinitionParser> parsers =
new HashMap<String, BeanDefinitionParser>();
private final Map<String, BeanDefinitionDecorator> decorators =
new HashMap<String, BeanDefinitionDecorator>();
private final Map<String, BeanDefinitionDecorator> attributeDecorators =
new HashMap<String, BeanDefinitionDecorator>();
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
String localName = parserContext.getDelegate().getLocalName(element);
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}
@Override
public BeanDefinitionHolder decorate(
Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
return findDecoratorForNode(node, parserContext).decorate(node, definition, parserContext);
}
private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) {
BeanDefinitionDecorator decorator = null;
String localName = parserContext.getDelegate().getLocalName(node);
if (node instanceof Element) {
decorator = this.decorators.get(localName);
}
else if (node instanceof Attr) {
decorator = 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;
}
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);
}
}
====================================================
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
}
}
从这里我们可以看到解析MVC命名空间的所有解析器,其中解析annotation-driven的就是AnnotationDrivenBeanDefinitionParser。