Spring中DispatcherHandler的初始化过程

Spring Boot中HttpHandler的创建过程一文中,介绍到在WebFluxConfigurationSupport类中会向bean工厂中注册DispatcherHandler类型的bean。在创建后Spring会对该bean进行初始化,以满足处理请求的需要。本文就来分析一下初始化过程中做了哪些事情。


创建过程

java
spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
/*
 * 注册WebFlux的核心组件:DispatcherHandler,bean的名称为webHandler
 * bean的名称正如方法名:webHandler,
 * 在WebHttpHandlerBuilder中会被获取,使用的是常量属性WEB_HANDLER_BEAN_NAME,该常量的值就是webHandler。
 */
@Bean
public DispatcherHandler webHandler() {
    return new DispatcherHandler();
}

其实在WebFluxConfigurationSupport中,还会创建其他组件,如RouterFunctionMappingRequestMappingHandlerAdapter等。

DispatcherHandler构造方法

java
spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java
public DispatcherHandler() {
}
public DispatcherHandler(ApplicationContext applicationContext) {
    initStrategies(applicationContext);
}

该类有两个构造方法,但是上面调用的是无参构造方法,所以此时还不会执行初始化操作。

初始化过程

DispatcherHandler实现了ApplicationContextAware接口,所以被Spring创建bean后会调用setApplicationContext方法。

java
spring-webflux/src/main/java/org/springframework/web/reactive/DispatcherHandler.java
/*
 * 这个方法中获取的依赖在WebFluxConfigurationSupport中有注入,
 * 而@EnableWebFlux注解引入了配置类DelegatingWebFluxConfiguration,这个类就是前者的子类。
 * 在SpringBoot中可以不用指定@EnableWebFlux,而在WebFluxAutoConfiguration中定义了一个DelegatingWebFluxConfiguration的子类。
 */
protected void initStrategies(ApplicationContext context) {
    /*
     * 从容器上下文中获取HandlerMapping实例
     * 主要参考:RequestMappingHandlerMapping,注意这是reactive包下的,不是webmvc包下的,两个类同名。
     */
    Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerMapping.class, true, false);

    ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
    AnnotationAwareOrderComparator.sort(mappings);
    this.handlerMappings = Collections.unmodifiableList(mappings);

    /*
     * 从容器上下文中获取HandlerAdapter实例
     * 主要参考:RequestMappingHandlerAdapter,注意这是reactive包下的,不是webmvc包下的,两个类同名。
     */
    Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerAdapter.class, true, false);

    this.handlerAdapters = new ArrayList<>(adapterBeans.values());
    AnnotationAwareOrderComparator.sort(this.handlerAdapters);

    /*
     * 从容器中获取HandlerResultHandler实例
     * 主要参考:ResponseBodyResultHandler,这个最常用。
     */
    Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerResultHandler.class, true, false);

    this.resultHandlers = new ArrayList<>(beans.values());
    AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

该方法中主要是在获取3种类型的bean,后续处理请求时会被用到。

  • HandlerMapping:默认情况下会注册下面3种类型的bean,越靠前优先级越高。
    • RouterFunctionMapping
    • RequestMappingHandlerMapping;
    • SimpleUrlHandlerMapping
  • HandlerAdapter:默认情况下会注册下面4种类型的bean,越靠前的优先级越高。
    • WebSocketHandlerAdapter
    • RequestMappingHandlerAdapter
    • HandlerFunctionAdapter
    • SimpleHandlerAdapter
  • HandlerResultHandler:默认情况下会注册下面4种类型的bean,越靠前的优先级越高。
    • ResponseEntityResultHandler
    • ServerResponseResultHandler;
    • ResponseBodyResultHandler
    • ViewResolutionResultHandler

一般来说我们大部分时候都是使用的RequestMappingHandlerMappingRequestMappingHandlerAdapterResponseBodyResultHandler

在Spring Cloud Gateway中,会使用到RoutePredicateHandlerMapping(Spring Cloud Gateway中提供的类)和SimpleHandlerAdapter