3. spring-cloud-gateway 自动装配与handle入口

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方法详解。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值