SpringMVC Interceptor 解析,加载源码流程

SpringMVC Interceptor 解析,加载源码流程

本文说什么

interceptor从哪里来,怎么创建,怎么加载,在哪里被使用,以xml的配置形式为例

xml配置解析阶段

直接打开spring-webmvc的源码包找到spring.handlers,这个是spring对于组件xml解析模块。
在这里插入图片描述

打开后一看说明,mvc这个标签是,是通过这个 org.springframework.web.servlet.config.MvcNamespaceHandler,解析的直接找到看一下

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler

发现是

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 GroovyMarkupConfigurerBeanDefinitionParser());
	}

}

这个就直接找到<mvc:*> 的所有表现对应的解析类了,直接找到

registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());

打开看一下,


	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compDefinition);

		RuntimeBeanReference pathMatcherRef = null;
		if (element.hasAttribute("path-matcher")) {
			pathMatcherRef = new RuntimeBeanReference(element.getAttribute("path-matcher"));
		}

		List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
		for (Element interceptor : interceptors) {
			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;
			if ("interceptor".equals(interceptor.getLocalName())) {
				includePatterns = getIncludePatterns(interceptor, "mapping");
				excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
				Element beanElem = DomUtils.getChildElementsByTagName(interceptor, "bean", "ref").get(0);
				interceptorBean = parserContext.getDelegate().parsePropertySubElement(beanElem, null);
			}
			else {
				interceptorBean = parserContext.getDelegate().parsePropertySubElement(interceptor, null);
			}
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
			mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);

			if (pathMatcherRef != null) {
				mappedInterceptorDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
			}

			String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
			parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

就找到了对于这些标签的解析,然后把 interceptors 节点全部生成对应的RootBeanDefinition放入到spring容器中,对于xml的解析都结束了容器中已经都全部的interceptor了

加载interceptor

直接找 AbstractHandlerMapping 这个类,handlerMapping的基础实现类,里面把interceptor 初始化,分类。因为他继承实现了webapplicationObjectSupport。有几个初始化方法,这就是初始化把interceptor的入口

org.springframework.web.servlet.handler.AbstractHandlerMapping

在这里插入图片描述

sping注入applicationContext,就是调用 初始化的时候调用 initApplicationContext 中开始填充handlerMapping中的intercetor 集合
入口代码展示


pjavaublic abstract class ApplicationObjectSupport implements ApplicationContextAware {
		.........
@Override
	public final void setApplicationContext(ApplicationContext context) throws BeansException {
		if (context == null && !isContextRequired()) {
			// Reset internal context state.
			this.applicationContext = null;
			this.messageSourceAccessor = null;
		}
		else if (this.applicationContext == null) {
			// Initialize with passed-in context.
			if (!requiredContextClass().isInstance(context)) {
				throw new ApplicationContextException(
						"Invalid application context: needs to be of type [" + requiredContextClass().getName() + "]");
			}
			this.applicationContext = context;
			this.messageSourceAccessor = new MessageSourceAccessor(context);
			initApplicationContext(context); // 入口 入口 入口 入口 入口 入口 
		}
		else {
			// Ignore reinitialization if same context passed in.
			if (this.applicationContext != context) {
				throw new ApplicationContextException(
						"Cannot reinitialize with different application context: current one is [" +
						this.applicationContext + "], passed-in one is [" + context + "]");
			}
		}
	}
	
	protected void initApplicationContext(ApplicationContext context) throws BeansException {
		initApplicationContext();
	}

	protected void initApplicationContext() throws BeansException {
		//子类实现
	}
		.........
	}

public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
		implements HandlerMapping, Ordered {
	.......
	@Override
	protected void initApplicationContext() throws BeansException {
		extendInterceptors(this.interceptors);
		detectMappedInterceptors(this.mappedInterceptors);//从spring中找到interceptor
		initInterceptors();
	}
	
	/**
	 * 在容器中找到所有的interceptor,一个个放入 AbstractHandlerMapping,然后在对其初始化分类,后面就可以用了
	 **/
	
	protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
		mappedInterceptors.addAll(
				BeanFactoryUtils.beansOfTypeIncludingAncestors(
						getApplicationContext(), MappedInterceptor.class, true, false).values());
	}

	/**
	 * 分类
	 **/
	protected void initInterceptors() {
		if (!this.interceptors.isEmpty()) {
			for (int i = 0; i < this.interceptors.size(); i++) {
				Object interceptor = this.interceptors.get(i);
				if (interceptor == null) {
					throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
				}
				if (interceptor instanceof MappedInterceptor) {
					this.mappedInterceptors.add((MappedInterceptor) interceptor);
				}
				else {
					this.adaptedInterceptors.add(adaptInterceptor(interceptor));
				}
			}
		}
	}
	......

}

这样整个流程就搞一段落

总结

mvc自己的包,自己定义标签,解析xml把所有的interceptor放入spring中,在初始化handlerMapping 中在一个个找出来,放到 handlermapping 中,在初始化分类准备后面使用

ps:
MappedInterceptor 包换 MappedInterceptor

public final class MappedInterceptor {

	// 需要拦截的url
	private final String[] includePatterns;
	// 排除的url
	private final String[] excludePatterns;

	private final HandlerInterceptor interceptor;
	// 判断是否符合
	private PathMatcher pathMatcher;

猜你喜欢

转载自blog.csdn.net/qq_33221085/article/details/83108975