SpringMVC源码情操陶冶-InterceptorsBeanDefinitionParser拦截器解析器

解析mvc:interceptors节点

观察下InterceptorsBeanDefinitionParser的源码备注

/**
 * {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
 * {@code interceptors} element to register a set of {@link MappedInterceptor} definitions.
 *
 * @author Keith Donald
 * @since 3.0
 */

从官方注释可知,此解析器的作用是解析mvc:interceptors节点并注册成MappedInterceptorsDefinition集合

mvc:interceptors的配置使用

    <!-- 拦截器设置 -->
    <mvc:interceptors>
    	<mvc:interceptor>
    		<mvc:mapping path="/**"/>
			  <!-- 静态资源不拦截 -->  		
    		<mvc:exclude-mapping path="/mobile/**"/>
    		<mvc:exclude-mapping path="/pc/**"/>
    		<!-- 主页不拦截 -->
    		
    		<!-- 特殊user资源获取不拦截 -->
    		<bean class="com.du.wx.interceptor.UserInterceptor" />
    	</mvc:interceptor>
    </mvc:interceptors>

InterceptorsBeanDefinitionParser#parse

直接观察公用接口方法parse(),源码奉上

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		//CompositeComponentDefinition表示其可以装载多个ComponentDefinition
		CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compDefinition);
		
		//允许mvc:interceptors拥有path-matcher属性,表示 路径匹配解析器
		RuntimeBeanReference pathMatcherRef = null;
		if (element.hasAttribute("path-matcher")) {
			pathMatcherRef = new RuntimeBeanReference(element.getAttribute("path-matcher"));
		}
		//查询mvc:interceptors节点下的bean/ref/interceptor标签
		List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
		for (Element interceptor : interceptors) {
			//采用MappedInterceptor作为beanClass
			RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
			mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
			mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

			ManagedList<String> includePatterns = null;
			ManagedList<String> excludePatterns = null;
			Object interceptorBean;
			//解析mvc:interceptor节点
			if ("interceptor".equals(interceptor.getLocalName())) {
				//解析mvc:mapping节点中的path属性,保存里面的拦截路径集合
				includePatterns = getIncludePatterns(interceptor, "mapping");
				//解析mvc:exclude-mapping节点中的path属性,保存里面的放行路径集合
				excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
				//解析bean标签/ref标签,并封装成beanDefinition
				Element beanElem = DomUtils.getChildElementsByTagName(interceptor, "bean", "ref").get(0);
				interceptorBean = parserContext.getDelegate().parsePropertySubElement(beanElem, null);
			}
			else {
			//解析bean标签/ref标签,并封装成beanDefinition
				interceptorBean = parserContext.getDelegate().parsePropertySubElement(interceptor, null);
			}
			//MappedInterceptor类的构造函数可接受三个参数
			/**
			**public MappedInterceptor(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor)
			**
			*/
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);
			//为MappedInterceptor添加pathMatcher属性
			if (pathMatcherRef != null) {
				mappedInterceptorDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
			}
			//保存到spring的bean工厂中
			String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
			parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

小结

  • 解析mvc:interceptors,其会封装为MappedInterceptor类,进而保存
  1. 拦截路径匹配集合includePatterns
  2. 不拦截路径匹配集合excludePatterns
  3. 拦截处理器interceptor,其必须是HandlerInterceptor的实现类
  4. 路径匹配处理器,如果mvc:interceptors设定了path-matcher属性,默认为AntPathMatcher
  • MappedInterceptor其内部包含了HandlerInterceptor集合,并添加了路径的映射属性。对匹配的路径调用相应的HandlerInterceptors

  • mvc:interceptors注册的拦截器在AbstractHandlerMapping类中通过matches()方法被调用,具体调用见Springmvc源码

原文地址:https://www.cnblogs.com/question-sky/p/7077788.html