拦截器HandlerInterceptor初始化原理

本文详细介绍了在SpringMVC中通过三种方式配置拦截器:XML配置文件、Java配置类以及使用MappedInterceptor。内容包括如何在XML中解析`mvc:interceptors`标签,Java配置类中如何使用`@EnableWebMvc`和`@Configuration`,以及MappedInterceptor的使用示例。
// 配置拦截器(方式一)
<mvc:interceptors>
    // 会自动封装成MappedInterceptor
    <mvc:interceptor>
        <mvc:mapping path="/*"/>
        <bean class="com.luck.mvc.controller.LuckInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
// 解析interceptors标签
public BeanDefinition parse(Element element, ParserContext context) {
    // 解析XML表桥
    List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
    // 遍历拦截器标签
    for (Element interceptor : interceptors) {
        // 封装成MappedInterceptor对象
        RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
        mappedInterceptorDef.setSource(context.extractSource(interceptor));
        // 自己配置的包含路径和排除路径
        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 = context.getDelegate().parsePropertySubElement(beanElem, null);
        }
        // 给对象MappedInterceptor的构造方法赋值
        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 = context.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
        context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
    }
    return null;
}

配置拦截器(方式二)

@EnableWebMvc // 必须开启,否则无效
@Configuration
public class LuckConfig implements WebMvcConfigurer {
    @Bean
    public LuckInterceptor luckInterceptor() {
        return new LuckInterceptor();
    }

    // 添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(luckInterceptor()).addPathPatterns("/**");{
            InterceptorRegistration registration = new InterceptorRegistration(interceptor);
            // 注册到容器中
            this.registrations.add(registration);
            return registration;
        }
    }
}

@EnableWebMvc 导入了DelegatingWebMvcConfiguration类,内部注册了requestMappingHandlerMapping的Bean
    @Bean
	public RequestMappingHandlerMapping requestMappingHandlerMapping(
			@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
			@Qualifier("mvcConversionService") FormattingConversionService conversionService,
			@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {

		RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
		mapping.setOrder(0);
		mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider){
		    if (this.interceptors == null) {
                InterceptorRegistry registry = new InterceptorRegistry();
                // 将自己注册的拦截器
                addInterceptors(registry);{
                    // this.configurers = WebMvcConfigurerComposite implements WebMvcConfigurer
                    this.configurers.addInterceptors(registry);{
                        // 扫描所有的WebMvcConfigurer,添加拦截器,这就是为什么要实现WebMvcConfigurer接口
                        for (WebMvcConfigurer delegate : this.delegates) {
                            delegate.addInterceptors(registry);
                        }
                    }
                }
                // 注册内置的拦截器
                registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
                registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
                // 将拦截器注册表所有的拦截器
                this.interceptors = registry.getInterceptors();{
                    return this.registrations.stream()
                            .sorted(INTERCEPTOR_ORDER_COMPARATOR)
                            // 封装成MappedInterceptor
                            .map(InterceptorRegistration::getInterceptor){
                                // 如果没有自定义的拦截设置,直接返回,不包装
                                if (this.includePatterns == null && this.excludePatterns == null) {
                                    return this.interceptor;
                                }
                                // 否则包装成MappedInterceptor
                                MappedInterceptor mappedInterceptor = new MappedInterceptor(
                                        StringUtils.toStringArray(this.includePatterns),
                                        StringUtils.toStringArray(this.excludePatterns),
                                        this.interceptor);
                                // 如果存在路径匹配器
                                if (this.pathMatcher != null) {
                                    mappedInterceptor.setPathMatcher(this.pathMatcher);
                                }
                                return mappedInterceptor;
                            }
                            .collect(Collectors.toList());
                }
            }
		});
		return mapping;
	}

配置拦截器(方式三)
@Bean
public MappedInterceptor luckInterceptor() {
    return new MappedInterceptor(new String[]{"/**"}, new LuckInterceptor());
}
在AbstractHandlerMapping中,初始化的时候会执行
// 扫描自己注册的MappedInterceptorBean
detectMappedInterceptors(this.adaptedInterceptors);{
    // 从Spring容器中获取MappedInterceptor类型的bean
    mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
                    obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}

// 在所有的AbstractHandlerMapping中都会执行
// 拦截器存在AbstractHandlerMapping这个类中是因为Handler就是存在这里,而拦截器就是对handler进行处理的
class AbstractHandlerMapping extends WebApplicationObjectSupport
                             extends ApplicationObjectSupport implements ApplicationContextAware
		                     implements HandlerMapping{
    public final void setApplicationContext(@Nullable ApplicationContext context) {
        this.initApplicationContext(context);{
            // 空实现,是将所有配置的拦截器给子类继承,扩展
            // this.interceptors是在HandlerMapping中自己设置的
            // 如果是默认的HandlerMapping,那么是没有设置拦截器的
            // 如果是使用了@EnableMvc,导入的配置类中添加了HandlerMapping的Bean,这些bean中设置了拦截器
            extendInterceptors(this.interceptors);
            // 扫描MappedInterceptors,就是对原生的Interceptor进行了包装
            // 因为我们定义的Interceptor是可以设置匹配路径的,这样内部最少需要一个匹配器来校验
            // 所以才会有MappedInterceptors
            // 扫描我们自己定义的拦截器MappedInterceptors
            // this.adaptedInterceptors这个是我们适配之后,实实在在能用的拦截器
            detectMappedInterceptors(this.adaptedInterceptors);{
                // 从Spring容器中获取MappedInterceptor类型的bean
                mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
                				obtainApplicationContext(), MappedInterceptor.class, true, false).values());
            }
            // 初始化所有的拦截器
            initInterceptors();{
                // 遍历所有的拦截器
                for (int i = 0; i < this.interceptors.size(); i++) {
                    Object interceptor = this.interceptors.get(i);
                    // adaptedInterceptors是我们适配之后,实实在在能用的拦截器
                    this.adaptedInterceptors.add(adaptInterceptor(interceptor){
                                                    // 适配拦截器
                                                    if (interceptor instanceof HandlerInterceptor) {
                                                         return (HandlerInterceptor) interceptor;
                                                     }
                                                     // 转换为HandlerInterceptor类型
                                                     if (interceptor instanceof WebRequestInterceptor) {
                                                         return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
                                                     }
                                                });
                    }
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值