Java框架-Spring MVC理解006-xml文件中通过命名空间配置标签的解析过程

xml文件中通过命名空间配置标签的解析过程

在spring的xml文件中通过命名空间配置的标签是怎么解析的?
  我们都知道,在spring的xml配置文件中可以使用很多命名空间来配置,命名空间配置的内容具体是怎么解析的呢?对于一个具体的命名空间,spring是怎么找到解析它的类的呢?
  其实在spring中是把解析标签的类都放到了相应的META-INF目录下的spring.handlers文件中,然后从那里面找,比如,mvc命名空间的解析设置在spring-webmvc-4.1.5.RELEASE.jar包下META-INF/spring.handlers文件中,其内容为
http://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
这也就告诉我们,处理mvc这个命名空间的配置要使用MvcNamespaceHandler(在其内部将mvc:annotation-driven的解析交给AnnotationDrivenBeanDefinitionParser)。
解析配置的接口是org.springframework.beans.factory.xml.NamespaceHandler,它的继承结构如下(NamespaceHandlerSupport的子类有很多,图9-6只给出了MvcName-spaceHandler)。NamespaceHandler里一共定义了三个方法:init、parse和decorate。init是用来初始化自己的;parse用于将配置的标签转换成spring所需要的BeanDefinition;decorate是装饰的意思,decorate方法的作用是对所在的BeanDefinition进行一些修改,用得比较少。

//org.springframework.beans.factory.xml.NamespaceHandler
public interface NamespaceHandler {
void init();
BeanDefinition parse(Element element, ParserContext parserContext);
BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}

  NamespaceHandler的实现类主要有三个:NamespaceHandlerSupport、SimpleConstructorNamespaceHandler、SimplePropertyNamespaceHandler。其中NamespaceHandler-Support是NamespaceHandler的默认实现,一般的NamespaceHandler都继承自这个类(当然也有特殊情况,springSecurity的SecurityNamespaceHandler是直接实现的NamespaceHandler接口),SimpleConstructorNamespaceHandler用于统一对通过c:配置的构造方法进行解析,SimplePropertyNamespaceHandler用于统一对通过p:配置的参数进行解析。

  NamespaceHandlerSupport并没有做具体的解析工作,而是定义了三个处理器parsers、decorators、attributeDecorators,分别用于处理解析工作、处理标签类型、处理属性类型的装饰。接口的parse和decorate方法的执行方式是先找到相应的处理器,然后进行处理。具体的处理器由子类实现,然后注册到NamespaceHandlerSupport上面。所以要定义一个命名空间的解析器,只需要在init中定义相应的parsers、decorators、attributeDecorators并注册到NamespaceHandlerSupport上面。下面是NamespaceHandler-Support的代码以及解析mvc命名空间的MvcNamespaceHandler的代码:

package org.springframework.beans.factory.xml;
// 省略了imports
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);
}
}

package org.springframework.web.servlet.config;
// 省略了imports
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
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());
registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());
registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBean
DefinitionParser());
}
}

从这里就可以看到mvc命名空间使用到的所有解析器,其中解析“annotation-driven”的是AnnotationDrivenBeanDefinitionParser。
小结
  通过003、004、005我们分析了Spring MVC自身的创建过程,Spring MVC中Servlet一共有三个层次,分别是HttpServletBean、FrameworkServlet和DispatcherServlet。HttpServletBean直接继承自Java的HttpServlet,其作用是将Servlet中配置的参数设置到相应的属性;FrameworkServlet初始化了WebApplicationContext,DispatcherServlet初始化了自身的9个组件。FrameworkServlet初始化WebApplicationContext一共有三种方式,过程中使用了Servlet中配置的一些参数。
  整体结构非常简单——分三个层次做了三件事,但具体实现过程还是有点复杂的。这其实也是spring的特点:结构简单,实现复杂。结构简单主要是顶层设计好,实现复杂的主要是提供的功能比较多,可配置的地方也非常多。当然,正是因为实现复杂,才让Spring MVC使用起来更加灵活,这一点在后面会有更深刻的体会。如果能静下心来对照着源代码耐心地去看,还是很容易理解的。

原文地址:https://www.cnblogs.com/yulibo/p/9069519.html