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