文章目录
1. 概览
在上一篇分享的spring-cloud-gateway(以下简称gateway)的组织结构中,提到了gateway的自动装配类,本篇文章详细分享两个自动装配类,并从自动装配类开始引出gateway的处理入口handle,以期能够更好的理解gateway的工作原理。
2. GatewayAutoConfiguration
gateway的自动装配类中比较重要的是 GatewayAutoConfiguration, 它负责很多bean的初始化,它的类声明如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
GatewayClassPathWarningAutoConfiguration.class })
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
第一行,注解@Configuration(proxyBeanMethods = false)声明GatewayAutoConfiguration是一个配置类,proxyBeanMethods声明配置类不会被代理,主要是提高性能。
第二行,注解@ConditionalOnProperty(name = “spring.cloud.gateway.enabled”, matchIfMissing = true)声明在配置spring.cloud.gateway.enabled值为true时加载GatewayAutoConfiguration配置,默认值是true。
另外可以看到,它在HttpHandlerAutoConfiguration 和 WebFluxAutoConfiguration之前加载
在GatewayLoadBalancerClientAutoConfiguration 和 GatewayClassPathWarningAutoConfiguration之后加载。
我画了一张GatewayAutoConfiguration装配类的顺序图如下:
1. 从上到下的层级代表装配顺序
2. 红色先表示直接依赖,黑色线表示间接依赖
3. 黑色虚线框表示间接依赖的自动装配类依赖。
3. HttpHandlerAutoConfiguration
从上节的装配关系可以看出,GatewayAutoConfiguration装配后,又装配了HttpHandlerAutoConfiguration,它是一个非常重要的自动装配类,它为gateway注册 HttpHandler,注册的代码如下所示:
@Bean
public HttpHandler httpHandler(ObjectProvider<WebFluxProperties> propsProvider) {
HttpHandler httpHandler = WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
WebFluxProperties properties = propsProvider.getIfAvailable();
if (properties != null && StringUtils.hasText(properties.getBasePath())) {
Map<String, HttpHandler> handlersMap = Collections.singletonMap(properties.getBasePath(), httpHandler);
return new ContextPathCompositeHandler(handlersMap);
}
return httpHandler;
}
这一部分是webflux框架代码,想实现个性化的功能,注入自己的HttpHandler即可,Shenyu使用的也是同样的策略,Shenyu注入的是ShenyuWebHandler(细节可以参考本博客神禹解密相关文章)。gateway注入的HttpHandler叫DispatchHandler。
4. DispatcherHandler实例化
DispatcherHandler 在WebFluxConfigurationSupport类中实例化,代码如下所示:
@Bean
public DispatcherHandler webHandler() {
return new DispatcherHandler();
}
WebFluxConfigurationSupport有两个子类,DelegatingWebFluxConfiguration 和 EnableWebFluxConfiguration, 他们构成如下的继承关系
5. DispatcherHandler 详解
5.1 DispatcherHandler 类的实现关系
DispatcherHandler类实现了WebHandler和ApplicatonContextAware接口,构成了如下图所示的类继承关系
在Dispatcher的构造方法和ApplicatonContextAware结构的实现方法setApplicationContext中,均调用了initStrategies(Application applicaton)方法,代码如下所示
public DispatcherHandler(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
5.2 initStrategies方法
initStrategies方法的代码如下所示,它主要用来初始化一些内容,可以分为三部分,第一部分是初始化handlerMappings,第二部分是初始化handlerAdapters,第三部分是初始化resultHandlers。
protected void initStrategies(ApplicationContext context) {
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);
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
初始化这三部分有什么用呢,这就涉及到DispatcherHandler类中的另外一个方法,handle方法。
5.3 DispatcherHandler.handle()
handle方法是gateway请求处理的入口,它的代码如下所示:
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
.flatMap(handler -> invokeHandler(exchange, handler))
.flatMap(result -> handleResult(exchange, result));
}
它做了如下几件时间
1. 首先通过handlerMappings找到请求对应的handlerMapping
2. 通过mappings找到对应的handler方法,
3. 调用handler方法获取到结果,
4. 调用handleResult方法处理结果
有时间,我在分享handle方法详解。