Spring源码学习:SpringMVC(3)mvcannotation-driven标签解析【RequestMappingHandlerMapping生成】

前言

​ 上一篇我们已经完成了springmvc中子容器的初始化,子容器里面一般是一些和web相关的组件,其中的配置文件中就有mvc:annotation-driven这个标签,这里主要对这个标签来进行剖析,看下它里面干了一些什么,其实也是为了后面我们能通过请求url找到对应处理器方法完成的一个铺垫

mvc:annotation-driven标签概述

​ mvc:annotation-driven标签默认会开启SpringMVC的注解驱动模式,默认注册一个RequestMappingHandlerMapping、一个RequestMappingHandlerAdapter、一个ExceptionHandlerExceptionResolver。以支持对使用了 @RequestMapping 、 @ExceptionHandler 及其他注解的控制器方法的请求处理。

mvc:annotation-driven标签解析【RequestMappingHandlerMapping生成】

​ 首先这是一个XML标签,所以我们需要到Spring中refresh()核心方法中的obtainFreshBeanFactory()中里面的parseBeanDefinitions(root,delegate)方法那里打断点,找到解析 mvc:annotation-driven这个标签的逻辑

在这里插入图片描述

注意:node一定得是 mvc:annotation-driven这个标签

	public BeanDefinition parseCustomElement(Element ele) {
   
		return parseCustomElement(ele, null);
	}
	
		public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
   
		//解析节点的命名空间
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
   
			return null;
		}
		//解析命名空间,得到一个命名空间处理器
		//重点
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
   
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		//开始解析
		//主线 重点
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));\
	}

	public BeanDefinition parse(Element element, ParserContext parserContext) {
   
		//通过定义的标签属性(如:component-scan)获取对应的BeanDefinitionParser解析对象
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
		//执行解析   AnnotationDrivenBeanDefinitionParser.parse
		return (parser != null ? parser.parse(element, parserContext) : null);
	}

​ 关于定位自定义标签解析的过程,以后的IOC中会说明的,这里直接打开AnnotationDrivenBeanDefinitionParser类并定位到其parse方法

AnnotationDrivenBeanDefinitionParser#parse (解析入口)

/**
 * 解析 mvc:annotation-driven 标签
 */
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
   
    Object source = parserContext.extractSource(element);
    XmlReaderContext readerContext = parserContext.getReaderContext();

    CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
    parserContext.pushContainingComponent(compDefinition);

    /**
     * 获取协商内容视图配置
     */
    RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);

    /**
     * 创建RequestMappingHandlerMapping的RootBeanDefinition
     * 从这里也可以看出,开启mvc:annotation-driven标签后,
     * 将会默认注册RequestMappingHandlerMapping作为默认的HandlerMapping
     */
    RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
    handlerMappingDef.setSource(source);
    handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerMappingDef.getPropertyValues().add("order", 0);
    handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);

    // 是否开启矩阵变量
    if (element.hasAttribute("enable-matrix-variables")) {
   
        Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
        handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
    }

    // 解析path-matching路径匹配标签
    configurePathMatchingProperties(handlerMappingDef, element, parserContext);
    readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);

    // 解析cors跨域标签
    RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
    handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);

    // 解析conversion-service数据转换、格式化标签
    RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
    // 解析validator标签
    RuntimeBeanReference validator = getValidator(element, source, parserContext);
    // 解析message-codes-resolver标签
    RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);

    /**
     * 创建ConfigurableWebBindingInitializer的RootBeanDefinition对象
     * 并将上一步解析的conversionService、validator、messageCodesResolver
     * 作为属性注入到该对象中
     */
    RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
    bindingDef.setSource(source);
    bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    bindingDef.getPropertyValues().add("conversionService", conversionService);
    bindingDef.getPropertyValues().add("validator", validator);
    bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);

    // 解析message-converters标签
    ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
    // 解析argument-resolvers标签
    ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);
    // 解析return-value-handlers标签
    ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
    // 解析async-support标签
    String asyncTimeout = getAsyncTimeout(element);
    // 解析async-support的task-executor子标签
    RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
    // 解析async-support的callable-interceptors子标签
    ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, parserContext);
    // 解析async-support的deferred-result-interceptors子标签
    ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, parserContext);

    /**
     * 创建RequestMappingHandlerAdapter的RootBeanDefinition
     * 从这里也可以看出,开启mvc:annotation-driven标签后,
     * 将会默认注册RequestMappingHandlerAdapter作为默认的HandlerAdapter
     * 并将上面解析的内容绑定到该HandlerAdapter中
     */
    RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
    handlerAdapterDef.setSource(source);
    handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", content
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值