Spring WebFlux 工作原理分析 - 2.应用启动过程--6.WebFlux 自动配置

文章目录

  • 源代码
    • WebFluxAutoConfiguration
    • DelegatingWebFluxConfiguration
    • WebFluxConfigurationSupport
  • 总结

本系列以上的文章,到Spring WebFlux 工作原理分析 - 2.应用启动过程–3.更新应用上下文为止,其实我们已经得到了一个启动完成处于服务状态的Reactive Web Server。但是为了更深入了解其中的Reactive Web Server,我们通过以下篇幅对其创建和启动过程做了详细的分析:

  • Spring WebFlux 工作原理分析 - 2.应用启动过程–4.创建Web服务器
  • Spring WebFlux 工作原理分析 - 2.应用启动过程–5.启动Web服务器

基于以上的分析,我们知道:

  1. 缺省Spring WebFlux所使用的Reactive Web Server是一个基于NettyWeb服务器,
  2. 所使用的HttpHandler由应用上下文方法ReactiveWebServerApplicationContext#getHttpHandler所提供,
  3. 真正被使用的HttpHandler bean组件其实由HttpHandlerAutoConfiguration自动配置机制使用WebHttpHandlerBuilder结合当前应用上下文定义;

但是我们也看到,通过WebHttpHandlerBuilder构建HttpHandler bean过程中使用到了很多来自容器的bean组件 ,比如 :

  • WebHandler (1)
  • WebFilter (0…N)
  • WebExceptionHandler (0…N)
  • WebSessionManager (0|1)
  • ServerCodecConfigurer(0|1)
  • LocaleContextResolver(0|1)
  • ForwardedHeaderTransformer(0|1)

这些组件又是从哪里来的呢 ?为了弄明白这一点,我们就有必要了解一下Spring WebFlux工作组件的自动配置机制WebFluxAutoConfiguration

其实,WebFluxAutoConfigurationSpring Boot关于Spring WebFlux运行时工作组件的自动配置类。通过WebFluxAutoConfiguration自身以及其引入的内嵌配置类,Spring Boot加载了相应的配置参数,将各个工作组件作为bean注册到容器,并将开发人员或者框架自身所提供的WebFluxConfigurer配置应用到各个工作组件上。

源代码

源代码版本 : spring-webflux-5.1.8.RELEASE

WebFluxAutoConfiguration

package org.springframework.boot.autoconfigure.web.reactive;

// 省略 import 行

@Configuration
// 仅在 Reactive Web 环境下生效
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
// 仅在类 WebFluxConfigurer 存在于 classpath 上时生效
@ConditionalOnClass(WebFluxConfigurer.class)
// 仅在容器中不存在类型为 WebFluxConfigurationSupport 的bean时生效
// 本系列文章的例子应用中,开发人员没有定义类型为 WebFluxConfigurationSupport 的 bean,
// 所以该条件成立
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
// 在指定的自动配置机制应用之后应用
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class,
		ValidationAutoConfiguration.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebFluxAutoConfiguration {

    // 定义 bean hiddenHttpMethodFilter,类型 OrderedHiddenHttpMethodFilter
	@Bean
	@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
    // 仅在配置参数 spring.webflux.hiddenmethod.filter.enabled 不存在或者为 true 时生效
	@ConditionalOnProperty(prefix = "spring.webflux.hiddenmethod.filter", name = "enabled", matchIfMissing = true)
	public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
		return new OrderedHiddenHttpMethodFilter();
	}

    // 内嵌配置类
	@Configuration
    // 1. 加载前缀为`spring.resources`到`bean ResourceProperties`;
    // 2. 加载前缀为`spring.webflux`到`bean WebFluxProperties`;
	@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
    // 导入配置类 EnableWebFluxConfiguration
    // 配置类 EnableWebFluxConfiguration 是当前自动配置类的内嵌类,实现在下面
	@Import({ EnableWebFluxConfiguration.class })
    // 注意该配置类实现了接口 WebFluxConfigurer,
    // 导致它会被 EnableWebFluxConfiguration 用于配置 WebFlux 工作组件,
    // 参考 EnableWebFluxConfiguration 基类 DelegatingWebFluxConfiguration 的方法 :
    // 1. #setConfigurers , 会通过自动装配机制注入容器中所有的 WebFluxConfigurer, 这里就是
    // WebFluxConfig 被引入的地方;
    // 2. 基类DelegatingWebFluxConfiguration中其他各个 #addXXX,#configureXXX,#getXXX
    // 模板方法实现会使用所引入的 WebFluxConfigurer 以配置各种 WebFlux 工作组件;    
	public static class WebFluxConfig implements WebFluxConfigurer {

		private static final Log logger = LogFactory.getLog(WebFluxConfig.class);

       //前缀为 spring.resources 的配置项,构造函数注入
		private final ResourceProperties resourceProperties;

       // 前缀为 spring.webflux 的配置项,构造函数注入
		private final WebFluxProperties webFluxProperties;

       // 容器,构造函数注入 
		private final ListableBeanFactory beanFactory;

       // 请求处理器参数解析器,构造函数注入 
		private final ObjectProvider<HandlerMethodArgumentResolver> argumentResolvers;

		private final ObjectProvider<CodecCustomizer> codecCustomizers;

		private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;

       // 视图解析器 , 构造函数注入 
		private final ObjectProvider<ViewResolver> viewResolvers;

		public WebFluxConfig(ResourceProperties resourceProperties, WebFluxProperties webFluxProperties,
				ListableBeanFactory beanFactory, ObjectProvider<HandlerMethodArgumentResolver> resolvers,
				ObjectProvider<CodecCustomizer> codecCustomizers,
				ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizer,
				ObjectProvider<ViewResolver> viewResolvers) {
			this.resourceProperties = resourceProperties;
			this.webFluxProperties = webFluxProperties;
			this.beanFactory = beanFactory;
          // 参数解析器  
			this.argumentResolvers = resolvers;
			this.codecCustomizers = codecCustomizers;
			this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizer.getIfAvailable();
			this.viewResolvers = viewResolvers;
		}

		@Override
		public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
			this.argumentResolvers.orderedStream().forEach(configurer::addCustomResolver);
		}

		@Override
		public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
			this.codecCustomizers.orderedStream().forEach((customizer) -> customizer.customize(configurer));
		}


       // 静态资源处理器配置 
       // /webjars/** => classpath:/META-INF/resources/webjars/
		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
            
          // /webjars/** => classpath:/META-INF/resources/webjars/  
			if (!registry.hasMappingForPattern("/webjars/**")) {
				ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/");
				configureResourceCaching(registration);
				customizeResourceHandlerRegistration(registration);
			}
            
          // 根据配置参数决定是否要添加静态资源处理器  , 比如如下配置文件将会导致这里注册一项 
          // ResourceHandlerRegistration :
          // 
          // spring :
          //   webflux :
          //     static-path-pattern : /static/**
          //   resources :
          //     static-locations : /tmp
          // 
			String staticPathPattern = this.webFluxProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
				ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern)
						.addResourceLocations(this.resourceProperties.getStaticLocations());
				configureResourceCaching(registration);
				customizeResourceHandlerRegistration(registration);
			}
		}

		private void configureResourceCaching(ResourceHandlerRegistration registration) {
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			ResourceProperties.Cache.Cachecontrol cacheControl = this.resourceProperties.getCache().getCachecontrol();
			if (cachePeriod != null && cacheControl.getMaxAge() == null) {
				cacheControl.setMaxAge(cachePeriod);
			}
			registration.setCacheControl(cacheControl.toHttpCacheControl());
		}

		@Override
		public void configureViewResolvers(ViewResolverRegistry registry) {
           // 将当前配置器所发现的 viewResolvers 注册到 registry
			this.viewResolvers.orderedStream().forEach(registry::viewResolver);
		}

		@Override
		public void addFormatters(FormatterRegistry registry) {
          // 从容器中获取如下类型所有的类型转换器添加到 registry :
          //  Converter, GenericConverter, Formatter       
			for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
				registry.addConverter(converter);
			}
			for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
				registry.addConverter(converter);
			}
			for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
				registry.addFormatter(formatter);
			}
		}

		private <T> Collection<T> getBeansOfType(Class<T> type) {
			return this.beanFactory.getBeansOfType(type).values();
		}

		private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
			if (this.resourceHandlerRegistrationCustomizer != null) {
				this.resourceHandlerRegistrationCustomizer.customize(registration);
			}

		}

	}

   // 内嵌配置类,
   // 1. 继承自 DelegatingWebFluxConfiguration,以应用容器中的各个 WebFluxConfigurer(比如上面的 WebFluxConfig)
   // 2. 继承自 WebFluxConfigurationSupport, 以应用缺省的 WebFlux 组件配置逻辑,主要是定义各个组件bean
   // 使用此配置类相当于使用了注解 @EnableWebFlux, 因为注解 @EnableWebFlux 其实是直接导入了 
   // DelegatingWebFluxConfiguration : @Import(DelegatingWebFluxConfiguration.class) ,
   // 而 EnableWebFluxConfiguration 则是继承自 DelegatingWebFluxConfiguration 并做了一些扩展定制,
   // 上面的 WebFluxConfig 就会导入该类
	/**
	 * Configuration equivalent to {@code @EnableWebFlux}.
	 */
	@Configuration
	public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {

		private final WebFluxProperties webFluxProperties;

		private final WebFluxRegistrations webFluxRegistrations;

		public EnableWebFluxConfiguration(WebFluxProperties webFluxProperties,
				ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
			this.webFluxProperties = webFluxProperties;
			this.webFluxRegistrations = webFluxRegistrations.getIfUnique();
		}

       // 覆盖定义 bean webFluxConversionService,考虑到了配置文件属性中设置的日期格式
		@Bean
		@Override
		public FormattingConversionService webFluxConversionService() {
			WebConversionService conversionService = new WebConversionService(this.webFluxProperties.getDateFormat());
			addFormatters(conversionService);
			return conversionService;
		}

       // 覆盖定义 bean webFluxValidator 
		@Bean
		@Override
		public Validator webFluxValidator() {
			if (!ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
				return super.webFluxValidator();
			}
			return ValidatorAdapter.get(getApplicationContext(), getValidator());
		}

       // 覆盖定义基类方法 createRequestMappingHandlerAdapter, 
       // 优先使用 webFluxRegistrations 配置,如果无 webFluxRegistrations 配置,使用基类缺省逻辑
		@Override
		protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
			if (this.webFluxRegistrations != null
					&& this.webFluxRegistrations.getRequestMappingHandlerAdapter() != null) {
				return this.webFluxRegistrations.getRequestMappingHandlerAdapter();
			}
			return super.createRequestMappingHandlerAdapter();
		}

       // 覆盖定义基类方法 RequestMappingHandlerMapping, 
       // 优先使用 webFluxRegistrations 配置,如果无 webFluxRegistrations 配置,使用基类缺省逻辑
		@Override
		protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
			if (this.webFluxRegistrations != null
					&& this.webFluxRegistrations.getRequestMappingHandlerMapping() != null) {
				return this.webFluxRegistrations.getRequestMappingHandlerMapping();
			}
			return super.createRequestMappingHandlerMapping();
		}

	}

	@Configuration
	@ConditionalOnEnabledResourceChain
	static class ResourceChainCustomizerConfiguration {

		@Bean
		public ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() {
			return new ResourceChainResourceHandlerRegistrationCustomizer();
		}

	}

}

从上面的代码可见,WebFluxAutoConfiguration在条件满足的情况下,主要做了如下事情 :

  1. 定义WebFilter bean : OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter;
  2. 定义内部配置类WebFluxConfig,实现自接口WebFluxConfigurer;
  3. 定义内部配置类 EnableWebFluxConfiguration,继承自DelegatingWebFluxConfiguration,以应用各个WebFluxConfigurer和定义工作组件bean;
  4. 通过内部配置类WebFluxConfig导入EnableWebFluxConfiguration,相当于触发自身这个WebFluxConfigurer的应用,以及工作组件的定义;

这一动作相当于使用了注解@EnableWebFlux,只不过EnableWebFluxConfiguration@EnableWebFlux多了一些扩展定制。

接下来,我们看看EnableWebFluxConfiguration的两个基类DelegatingWebFluxConfigurationWebFluxConfigurationSupport,它们是EnableWebFluxConfiguration完成任务的主要类,分别负责 :

  1. DelegatingWebFluxConfiguration – 获取容器中的各个WebFluxConfigurer以便配置WebFlux工作组件;
  2. WebFluxConfigurationSupport – 提供子类可以覆盖i的模板方法,并定义各种WebFlux工作组件;

DelegatingWebFluxConfiguration


package org.springframework.web.reactive.config;

// 省略 import 行

/**
 * A subclass of {@code WebFluxConfigurationSupport} that detects and delegates
 * to all beans of type {@link WebFluxConfigurer} allowing them to customize the
 * configuration provided by {@code WebFluxConfigurationSupport}. This is the
 * class actually imported by {@link EnableWebFlux @EnableWebFlux}.
 *
 * @author Brian Clozel
 * @since 5.0
 */
@Configuration
public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {

    // 一个 WebFluxConfigurerComposite 是多个 WebFluxConfigurer 的组合
	private final WebFluxConfigurerComposite configurers = new WebFluxConfigurerComposite();

    
    // 自动装配,容器中所有的 WebFluxConfigurer
	@Autowired(required = false)
	public void setConfigurers(List<WebFluxConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebFluxConfigurers(configurers);
		}
	}

   // 应用各个 WebFluxConfigurer#configureContentTypeResolver 到  RequestedContentTypeResolverBuilder builder
	@Override
	protected void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
		this.configurers.configureContentTypeResolver(builder);
	}

   //  应用各个 WebFluxConfigurer#addCorsMappings 到  CorsRegistry registry
	@Override
	protected void addCorsMappings(CorsRegistry registry) {
		this.configurers.addCorsMappings(registry);
	}

   //  应用各个 WebFluxConfigurer#configurePathMatching 到  PathMatchConfigurer configurer 
	@Override
	public void configurePathMatching(PathMatchConfigurer configurer) {
		this.configurers.configurePathMatching(configurer);
	}

   //  应用各个 WebFluxConfigurer#addResourceHandlers 到  ResourceHandlerRegistry registry  
	@Override
	protected void addResourceHandlers(ResourceHandlerRegistry registry) {
		this.configurers.addResourceHandlers(registry);
	}

   //  应用各个 WebFluxConfigurer#configureArgumentResolvers 到  ArgumentResolverConfigurer configurer  
	@Override
	protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
		this.configurers.configureArgumentResolvers(configurer);
	}

   //  应用各个 WebFluxConfigurer#configureHttpMessageCodecs 到  ServerCodecConfigurer configurer 
	@Override
	protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
		this.configurers.configureHttpMessageCodecs(configurer);
	}

   //  应用各个 WebFluxConfigurer#addFormatters 到  FormatterRegistry registry  
	@Override
	protected void addFormatters(FormatterRegistry registry) {
		this.configurers.addFormatters(registry);
	}

    // 覆盖基类方法,优先使用各个 WebFluxConfigurer 定义的 Validator
	@Override
	protected Validator getValidator() {
		Validator validator = this.configurers.getValidator();
		return (validator != null ? validator : super.getValidator());
	}

    // 覆盖基类方法,优先使用各个 WebFluxConfigurer 定义的 MessageCodesResolver 
	@Override
	protected MessageCodesResolver getMessageCodesResolver() {
		MessageCodesResolver messageCodesResolver = this.configurers.getMessageCodesResolver();
		return (messageCodesResolver != null ? messageCodesResolver : super.getMessageCodesResolver());
	}

   //  应用各个 WebFluxConfigurer#configureViewResolvers 到  ViewResolverRegistry registry  
	@Override
	protected void configureViewResolvers(ViewResolverRegistry registry) {
		this.configurers.configureViewResolvers(registry);
	}
}

WebFluxConfigurationSupport

WebFluxConfigurationSupport是进行Spring WebFlux配置最主要的类,它可以直接被导入引用,或者扩展覆盖定制之后被导入引用。上面的类DelegatingWebFluxConfiguration就是WebFluxConfigurationSupport的子类。WebFluxAutoConfigurationDelegatingWebFluxConfiguration又定制了一层才导入引用。而注解@EnableWebFlux则是直接导入引用DelegatingWebFluxConfiguration。这一节我们看看WebFluxConfigurationSupport都做了什么。

package org.springframework.web.reactive.config;

// 省略 import 行

/**
 * The main class for Spring WebFlux configuration.
 *
 * 

Import directly or extend and override protected methods to customize. * * @author Rossen Stoyanchev * @author Brian Clozel * @since 5.0 */ // 实现了接口 ApplicationContextAware, 表示其实例会被容器设置应用上下文属性 public class WebFluxConfigurationSupport implements ApplicationContextAware { @Nullable private Map<String, CorsConfiguration> corsConfigurations; @Nullable private PathMatchConfigurer pathMatchConfigurer; @Nullable private ViewResolverRegistry viewResolverRegistry; @Nullable private ApplicationContext applicationContext; // ApplicationContextAware 接口约定的设置应用上下文属性的方法 @Override public void setApplicationContext(@Nullable ApplicationContext applicationContext) { this.applicationContext = applicationContext; if (applicationContext != null) { Assert.state(!applicationContext.containsBean("mvcContentNegotiationManager"), "The Java/XML config for Spring MVC and Spring WebFlux cannot both be enabled, " + "e.g. via @EnableWebMvc and @EnableWebFlux, in the same application."); } } @Nullable public final ApplicationContext getApplicationContext() { return this.applicationContext; } // 定义 bean DispatcherHandler webHandler // DispatcherHandler 可以认为是 Spring WebFlux 最核心的请求处理组件了,可以类比 // Spring MVC 的 DispatcherServlet @Bean public DispatcherHandler webHandler() { return new DispatcherHandler(); } // 定义 bean WebExceptionHandler responseStatusExceptionHandler // 缺省使用实现类 WebFluxResponseStatusExceptionHandler , 根据异常类型或者 // @ResponseStatus 注解信息获取 Http 状态码 @Bean @Order(0) public WebExceptionHandler responseStatusExceptionHandler() { return new WebFluxResponseStatusExceptionHandler(); } // 定义 bean RequestMappingHandlerMapping requestMappingHandlerMapping // 该 bean 管理 url pattern 到 handler 之间的映射, // 该方法主要是创建该bean自身和设置辅助工作组件,方法返回时bean中映射表为空 // RequestMappingHandlerMapping 实现了 InitializingBean 接口, // 所以它在对象初始化时会收集容器中所有的使用了注解 @Controller 或者注解 @RequestMapping // 的 handler 类中的控制器方法,形成 url pattern -- 控制器方法映射表 @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping(); mapping.setOrder(0); mapping.setContentTypeResolver(webFluxContentTypeResolver()); mapping.setCorsConfigurations(getCorsConfigurations()); PathMatchConfigurer configurer = getPathMatchConfigurer(); Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch(); if (useTrailingSlashMatch != null) { mapping.setUseTrailingSlashMatch(useTrailingSlashMatch); } Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch(); if (useCaseSensitiveMatch != null) { mapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch); } Map<String, Predicate<Class<?>>> pathPrefixes = configurer.getPathPrefixes(); if (pathPrefixes != null) { mapping.setPathPrefixes(pathPrefixes); } return mapping; } /** * Override to plug a sub-class of {@link RequestMappingHandlerMapping}. */ protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { return new RequestMappingHandlerMapping(); } // 定义 bean @Bean public RequestedContentTypeResolver webFluxContentTypeResolver() { RequestedContentTypeResolverBuilder builder = new RequestedContentTypeResolverBuilder(); configureContentTypeResolver(builder); return builder.build(); } /** * Override to configure how the requested content type is resolved. */ protected void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { } /** * Callback for building the global CORS configuration. This method is final. * Use {@link #addCorsMappings(CorsRegistry)} to customize the CORS conifg. */ protected final Map<String, CorsConfiguration> getCorsConfigurations() { if (this.corsConfigurations == null) { CorsRegistry registry = new CorsRegistry(); addCorsMappings(registry); this.corsConfigurations = registry.getCorsConfigurations(); } return this.corsConfigurations; } /** * Override this method to configure cross origin requests processing. * @see CorsRegistry */ protected void addCorsMappings(CorsRegistry registry) { } /** * Callback for building the {@link PathMatchConfigurer}. This method is * final, use {@link #configurePathMatching} to customize path matching. */ protected final PathMatchConfigurer getPathMatchConfigurer() { if (this.pathMatchConfigurer == null) { this.pathMatchConfigurer = new PathMatchConfigurer(); configurePathMatching(this.pathMatchConfigurer); } return this.pathMatchConfigurer; } /** * Override to configure path matching options. */ public void configurePathMatching(PathMatchConfigurer configurer) { } // 定义 bean RouterFunctionMapping routerFunctionMapping // 这是一组基于 RouterFunction 的 url 到 handler 的映射关系, // 这里的 handler 是一个 HandlerFunction // RouterFunctionMapping 实现了 InitializingBean 接口, // 所以它在对象初始化时会收集容器中所有的 RouterFunction @Bean public RouterFunctionMapping routerFunctionMapping() { RouterFunctionMapping mapping = createRouterFunctionMapping(); mapping.setOrder(-1); // go before RequestMappingHandlerMapping mapping.setMessageReaders(serverCodecConfigurer().getReaders()); mapping.setCorsConfigurations(getCorsConfigurations()); return mapping; } /** * Override to plug a sub-class of {@link RouterFunctionMapping}. */ protected RouterFunctionMapping createRouterFunctionMapping() { return new RouterFunctionMapping(); } /** * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped * resource handlers. To configure resource handling, override * {@link #addResourceHandlers}. */ // 定义 bean HandlerMapping resourceHandlerMapping 管理静态资源映射 // 如果没有配置静态资源映射,实现类为 EmptyHandlerMapping,内部映射表为空 // 如果存在静态资源映射,实现类为 SimpleUrlHandlerMapping, 内部映射表不为空 @Bean public HandlerMapping resourceHandlerMapping() { ResourceLoader resourceLoader = this.applicationContext; if (resourceLoader == null) { resourceLoader = new DefaultResourceLoader(); } ResourceHandlerRegistry registry = new ResourceHandlerRegistry(resourceLoader); registry.setResourceUrlProvider(resourceUrlProvider()); addResourceHandlers(registry); AbstractHandlerMapping handlerMapping = registry.getHandlerMapping(); if (handlerMapping != null) { PathMatchConfigurer configurer = getPathMatchConfigurer(); Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch(); Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch(); if (useTrailingSlashMatch != null) { handlerMapping.setUseTrailingSlashMatch(useTrailingSlashMatch); } if (useCaseSensitiveMatch != null) { handlerMapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch); } } else { handlerMapping = new EmptyHandlerMapping(); } return handlerMapping; } // 定义 bean @Bean public ResourceUrlProvider resourceUrlProvider() { return new ResourceUrlProvider(); } /** * Override this method to add resource handlers for serving static resources. * @see ResourceHandlerRegistry */ protected void addResourceHandlers(ResourceHandlerRegistry registry) { } // 定义 bean @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setMessageReaders(serverCodecConfigurer().getReaders()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry()); ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer(); configureArgumentResolvers(configurer); adapter.setArgumentResolverConfigurer(configurer); return adapter; } /** * Override to plug a sub-class of {@link RequestMappingHandlerAdapter}. */ protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { return new RequestMappingHandlerAdapter(); } /** * Configure resolvers for custom controller method arguments. */ protected void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { } /** * Return the configurer for HTTP message readers and writers. *

Use {@link #configureHttpMessageCodecs(ServerCodecConfigurer)} to * configure the readers and writers. */ @Bean public ServerCodecConfigurer serverCodecConfigurer() { ServerCodecConfigurer serverCodecConfigurer = ServerCodecConfigurer.create(); configureHttpMessageCodecs(serverCodecConfigurer); return serverCodecConfigurer; } /** * Override to plug a sub-class of {@link LocaleContextResolver}. */ protected LocaleContextResolver createLocaleContextResolver() { return new AcceptHeaderLocaleContextResolver(); } @Bean public LocaleContextResolver localeContextResolver() { return createLocaleContextResolver(); } /** * Override to configure the HTTP message readers and writers to use. */ protected void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { } /** * Return the {@link ConfigurableWebBindingInitializer} to use for * initializing all {@link WebDataBinder} instances. */ protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() { ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer(); initializer.setConversionService(webFluxConversionService()); initializer.setValidator(webFluxValidator()); MessageCodesResolver messageCodesResolver = getMessageCodesResolver(); if (messageCodesResolver != null) { initializer.setMessageCodesResolver(messageCodesResolver); } return initializer; } /** * Return a {@link FormattingConversionService} for use with annotated controllers. *

See {@link #addFormatters} as an alternative to overriding this method. */ @Bean public FormattingConversionService webFluxConversionService() { FormattingConversionService service = new DefaultFormattingConversionService(); addFormatters(service); return service; } /** * Override this method to add custom {@link Converter} and/or {@link Formatter} * delegates to the common {@link FormattingConversionService}. * @see #webFluxConversionService() */ protected void addFormatters(FormatterRegistry registry) { } /** * Return a {@link ReactiveAdapterRegistry} to adapting reactive types. */ @Bean public ReactiveAdapterRegistry webFluxAdapterRegistry() { return new ReactiveAdapterRegistry(); } /** * Return a global {@link Validator} instance for example for validating * {@code @RequestBody} method arguments. *

Delegates to {@link #getValidator()} first. If that returns {@code null} * checks the classpath for the presence of a JSR-303 implementations * before creating a {@code OptionalValidatorFactoryBean}. If a JSR-303 * implementation is not available, a "no-op" {@link Validator} is returned. */ // 定义 bean @Bean public Validator webFluxValidator() { Validator validator = getValidator(); if (validator == null) { if (ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) { Class<?> clazz; try { String name = "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean"; clazz = ClassUtils.forName(name, getClass().getClassLoader()); } catch (ClassNotFoundException | LinkageError ex) { throw new BeanInitializationException("Failed to resolve default validator class", ex); } validator = (Validator) BeanUtils.instantiateClass(clazz); } else { validator = new NoOpValidator(); } } return validator; } /** * Override this method to provide a custom {@link Validator}. */ @Nullable protected Validator getValidator() { return null; } /** * Override this method to provide a custom {@link MessageCodesResolver}. */ @Nullable protected MessageCodesResolver getMessageCodesResolver() { return null; } // 定义 bean @Bean public HandlerFunctionAdapter handlerFunctionAdapter() { return new HandlerFunctionAdapter(); } // 定义 bean @Bean public SimpleHandlerAdapter simpleHandlerAdapter() { return new SimpleHandlerAdapter(); } // 定义 bean @Bean public ResponseEntityResultHandler responseEntityResultHandler() { return new ResponseEntityResultHandler(serverCodecConfigurer().getWriters(), webFluxContentTypeResolver(), webFluxAdapterRegistry()); } // 定义 bean @Bean public ResponseBodyResultHandler responseBodyResultHandler() { return new ResponseBodyResultHandler(serverCodecConfigurer().getWriters(), webFluxContentTypeResolver(), webFluxAdapterRegistry()); } // 定义 bean @Bean public ViewResolutionResultHandler viewResolutionResultHandler() { ViewResolverRegistry registry = getViewResolverRegistry(); List<ViewResolver> resolvers = registry.getViewResolvers(); ViewResolutionResultHandler handler = new ViewResolutionResultHandler( resolvers, webFluxContentTypeResolver(), webFluxAdapterRegistry()); handler.setDefaultViews(registry.getDefaultViews()); handler.setOrder(registry.getOrder()); return handler; } // 定义 bean @Bean public ServerResponseResultHandler serverResponseResultHandler() { List<ViewResolver> resolvers = getViewResolverRegistry().getViewResolvers(); ServerResponseResultHandler handler = new ServerResponseResultHandler(); handler.setMessageWriters(serverCodecConfigurer().getWriters()); handler.setViewResolvers(resolvers); return handler; } /** * Callback for building the {@link ViewResolverRegistry}. This method is final, * use {@link #configureViewResolvers} to customize view resolvers. */ protected final ViewResolverRegistry getViewResolverRegistry() { if (this.viewResolverRegistry == null) { this.viewResolverRegistry = new ViewResolverRegistry(this.applicationContext); configureViewResolvers(this.viewResolverRegistry); } return this.viewResolverRegistry; } /** * Configure view resolution for supporting template engines. * @see ViewResolverRegistry */ protected void configureViewResolvers(ViewResolverRegistry registry) { } private static final class EmptyHandlerMapping extends AbstractHandlerMapping { @Override public Mono<Object> getHandlerInternal(ServerWebExchange exchange) { return Mono.empty(); } } private static final class NoOpValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return false; } @Override public void validate(@Nullable Object target, Errors errors) { } } }

总结

从上面的代码可见,WebFluxAutoConfiguration的主要任务如下 :

  1. 定义bean OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter
  2. 引入配置类WebFluxConfig(实现了接口WebFluxConfigurer)
    1. 加载前缀为spring.resourcesbean ResourceProperties;
    2. 加载前缀为spring.webfluxbean WebFluxProperties;
    3. 引入配置类EnableWebFluxConfiguration
      1. 继承自DelegatingWebFluxConfiguration
        1. 应用容器中的各个WebFluxConfigurer
      2. 定义bean FormattingConversionService webFluxConversionService
        1. 实现类为DefaultFormattingConversionService
      3. 定义bean Validator webFluxValidator
      4. 继承自WebFluxConfigurationSupport
        1. 定义bean DispatcherHandler webHandler
          1. 实现了接口WebHandler
        2. 定义bean WebExceptionHandler responseStatusExceptionHandler
          1. 实现类为WebFluxResponseStatusExceptionHandler
        3. 定义bean RequestMappingHandlerMapping requestMappingHandlerMapping
        4. 定义bean RequestedContentTypeResolver webFluxContentTypeResolver
        5. 定义bean RouterFunctionMapping routerFunctionMapping
        6. 定义bean HandlerMapping resourceHandlerMapping
        7. 定义bean ResourceUrlProvider resourceUrlProvider
        8. 定义bean RequestMappingHandlerAdapter requestMappingHandlerAdapter
        9. 定义bean ServerCodecConfigurer serverCodecConfigurer
        10. 定义bean LocaleContextResolver localeContextResolver
          1. 实现类为AcceptHeaderLocaleContextResolver
        11. 定义bean ReactiveAdapterRegistry webFluxAdapterRegistry
        12. 定义bean HandlerFunctionAdapter handlerFunctionAdapter
        13. 定义bean SimpleHandlerAdapter simpleHandlerAdapter
        14. 定义bean ResponseEntityResultHandler responseEntityResultHandler
        15. 定义bean ResponseBodyResultHandler responseBodyResultHandler
        16. 定义bean ViewResolutionResultHandler viewResolutionResultHandler
        17. 定义bean ServerResponseResultHandler serverResponseResultHandler
    4. 引入配置类ResourceChainCustomizerConfiguration
      1. 定义bean ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer

你可能感兴趣的:(Spring,WebFlux)