WebFlux的自动装配

根据之前的经验,咱使用WebFlux的时候,主启动类上相对比于WebMvc来讲没有任何区别,那只有自动配置类可以控制WebFlux的装配了,那装配的自动配置类不难猜想应该是:WebFluxAutoConfiguration

1. WebFluxAutoConfiguration

@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
                     ValidationAutoConfiguration.class })
                     @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
                     public class WebFluxAutoConfiguration

可以发现它跟 WebMvcAutoConfiguration 几乎没什么太大的区别:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
                     @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
                     @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
                     @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
                                          ValidationAutoConfiguration.class })
                                          public class WebMvcAutoConfiguration

只不过判断条件不太一样而已,WebFlux 需要判断的应用类型为 REACTIVE ,而 WebMvc 为 SERVLET ;WebFlux 需要判断classpath下是否有 WebFluxConfigurer 类,而 WebMvc 需要的是 ServletDispatcherServletWebMvcConfigurer 三个类。

根据之前读 WebMvc 的自动配置,肯定要先走进 ReactiveWebServerFactoryAutoConfiguration ,看一眼嵌入式容器的配置。

2. ReactiveWebServerFactoryAutoConfiguration

果不其然,它会导入嵌入式容器工厂的配置类。由于在默认情况下,导入 spring-boot-starter-webflux ,默认使用 Netty 作为嵌入式容器,故此处 EmbeddedNetty 生效,生效的原因与之前 WebMvc 原理一致,不再赘述。

看一眼 EmbeddedNetty 都干了什么:

2.1 EmbeddedNetty

很明显它创建了一个 ReactorResourceFactory ,一个 NettyReactiveWebServerFactoryNettyReactiveWebServerFactory 从命名上看就知道它应该是类比于 WebMvc 中的 TomcatServletWebServerFactory ,那 ReactorResourceFactory 是什么呢?

2.2 ReactorResourceFactory

它的文档注释原文翻译:

Factory to manage Reactor Netty resources, i.e. LoopResources for event loop threads, and ConnectionProvider for the connection pool, within the lifecycle of a Spring ApplicationContext. This factory implements InitializingBean and DisposableBean and is expected typically to be declared as a Spring-managed bean.

在Spring ApplicationContext 的生命周期内,用于管理Reactor Netty资源的工厂,即用于事件循环线程的 LoopResources 和用于连接池的 ConnectionProvider

该工厂实现 InitializingBeanDisposableBean,通常应将其声明为Spring管理的Bean。

划重点:管理Reactor Netty资源的工厂,这个说法怎么感觉跟线程池似的?而且后面还有循环、连接池的概念,难不成它就类比于jdbc中的 DataSource?往里看它的成员:

注意第三个属性:connectionProviderSupplier ,它的创建方式是 ConnectionProvider.elastic ,突然感觉眼熟:前面看调度器的时候,对于 Reactor 的线程池就有一种 elastic 类型的!莫非它确实就是管理 ConnectionProvider 的?点开 ConnectionProvider 的 elastic 方法:

果然它就是一个连接的提供者,而且它还是 Pool ,换句话说,咱就可以简单的理解成它是 Reactor Netty 的连接池

实际Debug了一下,发现确实与咱的推测基本贴合:

img

果然有关于池的好多属性,而且下面有 selectworker 的概念,这就是 Netty 的核心。(12是因为我用的笔记本CPU是i7-8750H,6核12线程,所以这里是12)


ReactiveWebServerFactoryAutoConfiguration 看完之后,回到 WebFluxAutoConfiguration

它除了还要先处理 ValidationAutoConfigurationJSR-303校验之外,还要先处理一个 CodecsAutoConfiguration

3. CodecsAutoConfiguration

可以发现这里面只是注册了一个 json 转换器,以及日志工具。源码很简单,不过多解析。

接下来才是最核心的 WebFluxAutoConfiguration 。源码中它定义了三个内部类,咱一个一个来看:

4. WebFluxConfig

可以看到它又导入了一个 EnableWebFluxConfiguration ,而它就是下面第5章节的 EnableWebFluxConfiguration ,咱从上往下一样一样看。先看 WebFluxConfig 中的配置:

4.1 静态资源映射

可以发现它处理的逻辑几乎跟 WebMvc 部分一致!也是处理 webjars 的资源,以及 ResourceProperties 中的静态路径,默认情况下:

发现也是跟 WebMvc 部分一样的路径。

4.2 ViewResolver

可以发现这部分是配置 ViewResolver 的,不过默认情况下Debug发现并没有进入 ViewResolverRegistryregistry 方法中,暂且略过。

4.3 Converter和Formatter

这部分在 WebMvc 部分也是一模一样的,直接copy过来的!(不过这部分不是特别关键,而且之前也没有单独拿出来聊,小伙伴们知道这里是配置转换器的即可)

大概来看 WebFluxConfig 主要就配置了这几个组件,继续往下看:

5. EnableWebFluxConfiguration

先看一眼继承:

它继承了 DelegatingWebFluxConfiguration ,这个套路貌似跟 WebMvc 部分也是一样的!

至于这些 Delegating***Configuration 的作用咱之前也提到过,它就是 @EnableWebMvc 或者 @EnableWebFlux 注解导入的配置类:

它的作用小伙伴们还记得吗?只要在 SpringBoot 中标注了这样的注解,代表 SpringBoot 默认的自动配置类不生效,改由咱们自己接管配置 WebMvc 或者 WebFlux 。

下面来看它里面配置的组件:

5.1 FormattingConversionService

看这个类的名,大概也能联想到之前看 WebMvc 部分的那个参数类型转换器吧!而且代码几乎也一模一样。

5.2 Validator

很明显它是配置 JSR-303 参数校验的校验器。

5.3 HandlerMapping和HandlerAdapter

哇塞这不是咱之前在 WebMvc 部分常聊的两个配合 DispatcherServlet 的核心组件吗?对的,它在 WebFlux 中也是一样的其效果。

6. WebFluxConfigurationSupport

上面咱注意到了 EnableWebFluxConfiguration 继承了 DelegatingWebFluxConfiguration,而它又继承了 WebFluxConfigurationSupport ,这个配置类中还注册了一些组件:

6.1 DispatcherHandler

发现了 WebFlux 的核心前端控制器:**DispatcherHandler** ,它在这里注册了,而且比 DispatcherServlet 简单的多。

6.2 WebExceptionHandler

WebFlux 的异常状态响应处理器,见名知意,不再深扒。

6.3 RequestMappingHandlerMapping

可以发现这里真正创建了 RequestMappingHandlerMapping 组件。

6.4 RouterFunctionMapping

RequestMappingHandlerMapping 区别开来,它是函数式端点路由编程的Mapping处理器。至于它的作用,咱到第33篇再聊。

6.5 SimpleUrlHandlerMapping

注意看源码中第一个if结构下面,它用了一个 ResourceHandlerRegistry ,有没有感觉似曾相识?咱在前面看静态资源映射的时候见过它,它是处理静态资源的映射的。通常情况下咱的项目中会有一些静态资源,只要存在静态资源,它就会创建一个 SimpleUrlHandlerMapping 来真正处理静态资源的路径映射。通过Debug,发现确实存在(因为有应用图标 favicon.ico):

img

6.6 RequestMappingHandlerAdapter

这里真正创建了 RequestMappingHandlerAdapter

6.7 LocaleContextResolver

这个 LocaleContextResolver 组件从类名上就可以看出来它是与国际化相关的组件。

6.8 ReactiveAdapterRegistry

这个 ReactiveAdapterRegistry 类看上去应该是处理 Reactive 类型的,看一眼它的文档注释:

A registry of adapters to adapt Reactive Streams Publisher to/from various async/reactive types such as CompletableFuture, RxJava Observable, and others. By default, depending on classpath availability, adapters are registered for Reactor, RxJava 1, RxJava 2 types, CompletableFuture, and Java 9+ Flow.Publisher.

适配器注册表,用于使Reactive Streams Publisher适应各种异步/反应类型,例如CompletableFuture,RxJava Observable等。 默认情况下,根据类路径的可用性,为Reactor,RxJava 1,RxJava 2类型,CompletableFuture和Java 9+ Flow.Publisher注册适配器。

果然,它可以处理多种 Reactive Stream 的发布器,它提到了 Reactor 、RxJava 、jdk9版本的 Flow 等。

6.9 一组ResultHandler

WebFlux 提供了4种 ResultHandler ,每种功能已标注在源码中。

7. ResourceChainCustomizerConfiguration

在最底下还有一个,不过它的配置很简单:

发现它有一个 @ConditionalOnEnableResourceChain 注解,它的作用咱不深追究了,它实际是跟一个 application.properties 中的配置有关:spring.resources.chain.strategy.fixed.enabled ,如果它配置为true,这个条件才生效,默认不生效,不再深究。

8. 小结

  1. WebFluxAutoConfiguration 的配置整体与 WebMvcAutoConfiguration 非常相似,其中不乏包括几个核心组件。

  2. WebFluxAutoConfiguration 默认配置的Web容器是Netty而非 Tomcat 等传统 Servlet 容器。

  3. 大部分比较熟悉的组件都在 DelegatingWebFluxConfiguration 的父类 WebFluxConfigurationSupport 中注册。

最后更新于

这有帮助吗?