• Spring源码情操陶冶-自定义节点的解析


    本文承接前文Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,特开辟出一块新地来啃啃这块有意思的骨头

    自定义节点的类型

    我们常用的可分为spring/springmvc两类

    1. spring常用的节点类型
    • context类型
    1. context-component-scan-扫描包内的所有class类并注册为beanDefinition到spring上下文
    2. context-property-placeholder-加载外部的资源供spring调用,常用${}来使用外部文件的属性
    3. context-annotation-config-自动对注册的beanDefinition进行注解处理,常用context-component-scan来代替
    • aop类型
      aop-config-AOP模式使用配置
    • task类型
    1. task-annotation-driven-任务处理配置
    2. task-executor-任务线程池配置
    3. task-schedulertask-scheduled-tasks-预先任务处理配置
    1. springmvc常用的节点类型
    1. mvc-annotation-driven-mvc注解式配置,多与context-component-scan搭配使用
    2. mvc-interceptors-mvc拦截器配置
    3. mvc-resources-mvc静态资源访问配置
    4. mvc-freemarker-configurer/mvc-velocity-configurer/mvc-groovy-configurer-视图渲染器配置
    5. mvc-cors-跨域资源访问配置

    NamespaceHandlerSupport-基础支持抽象类

    NamespaceHandlerSupportNamespaceHandler接口的直接实现类,后续的自定义节点的解析类都是继承此类来进行扩展的。这里我们只关注NamespaceHandler的两个实现方法initparse

    • init()
      初始化方法,抽象类中并没有对其进行复写,主要由继承的子类去复写,目的是初始化自定义节点的相关解析类并保存至NamespaceHandlerSupport#parsersmap集合中

    • parse(Element element, ParserContext parserContext)
      主要调用方法,在Spring源码情操陶冶-DefaultBeanDefinitionDocumentReader#parseBeanDefinitions章节中我们提到其会调用NamespaceHandler的通用方法parse也就是此方法来进行相应节点的解析,代码如下

    	@Override
    	public BeanDefinition parse(Element element, ParserContext parserContext) {
    		//找到相应的解析器并进行解析
    		return findParserForElement(element, parserContext).parse(element, parserContext);
    	}
    

    顺藤摸瓜看下NamespaceHandlerSupport#findParserForElement方法

    private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    		//一般都是类似context-component-scan、mvc-resources这样的节点名
    		String localName = parserContext.getDelegate().getLocalName(element);
    		//此处显而易见可察觉通过parsers这个map集合获取相应的解析器
    		BeanDefinitionParser parser = this.parsers.get(localName);
    		if (parser == null) {
    			parserContext.getReaderContext().fatal(
    					"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    		}
    		return parser;
    	}
    

    由此得出我们可以稍微密切关注下子类对init()方法的复写,便可得出相关的自定义节点对应的BeanDefinitionParser解析器

    常用的NamespaceHandler实现类

    这里只分析ContextNamespaceHandler-spring context空间处理类MvcNamespaceHandler-springmvc空间处理类

    ContextNamespaceHandler-context空间处理类

    先瞧瞧代码,内部只有一个方法且也是复写方法init()

    @Override
    	public void init() {
    		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
    		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
    		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
    		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
    		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
    		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
    		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
    	}
    

    挑选几个重要的解析器来分析

    MvcNamespaceHandler-springmvc空间处理类

    瞧瞧代码

    @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 GroovyMarkupConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    	}
    

    挑选重要的几个解析器来分析

    AopNamespaceHandler-aop空间处理类

    简单的瞅下代码

    @Override
    	public void init() {
    		// In 2.0 XSD as well as in 2.1 XSD.
    		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
    
    		// Only in 2.0 XSD: moved to context namespace as of 2.1
    		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    	}
    

    此处我们就简单的分析aop-config节点对应的解析器>>>Spring源码情操陶冶-AOP之ConfigBeanDefinitionParser解析器

    TaskNamespaceHandler-task空间处理类

    TxNamespaceHandler-tx空间处理类

    小结

    通过分析spring与springmvc常用的自定义标签解析器,希望能帮助博主以及读者更好的了解spring与springmvc的工作原理,方便在分析问题时更加得心应手

  • 相关阅读:
    安卓 出现Cannot launch AVD in emulator 错误
    服务器架构中,集群,负载均衡,分布式有什么区别吗
    JavaScript事件
    替换节点内文本的万用函数
    DOM(Document Object Module,文档对象模型)为JavaScript提供完整,全面控制网页结构与内容的对象
    c++和java的区别
    解决Spark集群无法停止
    spark 作业调度
    hadoop,hbase,hive,zookeeper整合可行性分析及版本确定
    hadoop+spark+kudu
  • 原文地址:https://www.cnblogs.com/question-sky/p/6947008.html
Copyright © 2020-2023  润新知