zoukankan      html  css  js  c++  java
  • 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使用起来更加灵活,这一点在后面会有更深刻的体会。如果能静下心来对照着源代码耐心地去看,还是很容易理解的。

  • 相关阅读:
    [LOJ537] DNA 序列
    yum安装jdk
    centos7添加tomcat自启服务
    ajax下载文件的方法 php下载图片的方法
    kali linux dpkg安装和删除的方法
    javascript 曲线流光动画
    javascript获取曲线路径每个像素的坐标
    抓取微信小程序源码的方法
    javascript canvas拖尾效果
    php错误execution timed out (118.236064 sec), terminating解决方法
  • 原文地址:https://www.cnblogs.com/yulibo/p/9069519.html
Copyright © 2011-2022 走看看