SpringCloud Gateway自动装配实现流程详解
启动依赖
找到gateway的依赖,spring-cloud-starter-gateway
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
点进去之后找到它的依赖
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> <version>3.1.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-gateway-server</artifactId> <version>3.1.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>2.6.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.1.1</version> <scope>compile</scope> <optional>true</optional> </dependency> </dependencies>
从名称上可以判断spring-cloud-gateway-server是gateway的核心依赖,找到依赖包,看到如下结构
spring.factories是一些自动装配的类,如下可以看到
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayResilience4JCircuitBreakerAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration,\
org.springframework.cloud.gateway.config.SimpleUrlHandlerMappingGlobalCorsAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayReactiveLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayReactiveOAuth2AutoConfigurationorg.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.gateway.support.MvcFoundOnClasspathFailureAnalyzer
其中比较重要的是GatewayAutoConfiguration,负责很多bean的初始化,类声明如下:
@Configuration(proxyBeanMethods = false) @ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true) @EnableConfigurationProperties @AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class }) @AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class }) @ConditionalOnClass(DispatcherHandler.class) public class GatewayAutoConfiguration {
@AutoConfigureBefore
和@AutoConfigureAfter
分别是在之前和之后加载
其中HttpHandlerAutoConfiguration
和WebFluxAutoConfiguration
算是比较重要的装配类
WebFluxAutoConfiguration
先看WebFluxAutoConfiguration,类声明如下:
@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnClass(WebFluxConfigurer.class) @ConditionalOnMissingBean({ WebFluxConfigurationSupport.class }) @AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class, CodecsAutoConfiguration.class, ReactiveMultipartAutoConfiguration.class, ValidationAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class }) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) public class WebFluxAutoConfiguration {
其中部分代码如下:
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ WebProperties.class, WebFluxProperties.class }) @Import({ EnableWebFluxConfiguration.class }) @Order(0) public static class WebFluxConfig implements WebFluxConfigurer {
可以看到通过WebFluxAutoConfiguration 通过 WebFluxConfig 导入了 EnableWebFluxConfiguration
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({ WebProperties.class, ServerProperties.class }) public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
EnableWebFluxConfiguration继承于DelegatingWebFluxConfiguration
@Configuration(proxyBeanMethods = false) public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
DelegatingWebFluxConfiguration又继承于WebFluxConfigurationSupport
在WebFluxConfigurationSupport中可以看到很熟悉的东西
@Bean public DispatcherHandler webHandler() { //BeanName为webHandler return new DispatcherHandler(); }
有点联想到DispatcherSerlvet
,类似前端控制器
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->
可以看到DispatcherHandler
实现了WebHandler接口并实现了其中的handle
方法
public interface WebHandler { /** * Handle the web server exchange. * @param exchange the current server exchange * @return {@code Mono<Void>} to indicate when request handling is complete */ Mono<Void> handle(ServerWebExchange exchange); }
可以猜到handle
应该就是核心的处理方法,此时又有疑问,该方法什么时候被调用,被谁调用的
官方文档上提到WebHandler
上面还有一个关键的 API HttpHandler
For server request processing there are two levels of support.
HttpHandler: Basic contract for HTTP request handling with non-blocking I/O and Reactive Streams back pressure, along with adapters for Reactor Netty, Undertow, Tomcat, Jetty, and any Servlet 3.1+ container.
WebHandler API: Slightly higher level, general-purpose web API for request handling, on top of which concrete programming models such as annotated controllers and functional endpoints are built.
从上面的英文可以看到 HttpHandler
是比 WebHandler
更加底层的一个 API,也就是说很可能是由 HttpHandler 来调用 WebHandler (请求由下往上),那DispatcherHandler
作为 WebHandler
的一个实现,也很有可能会被HttpHandler
的具体实现所持有。
通过HttpHandler
的实现类不难找到HttpWebHandlerAdapter
就是我们要找的,并且持有一个WebHandher
对象,当然也可以通过断点调试找到。
public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHandler {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->
HttpWebHandlerAdapter
继承于WebHandlerDecorator
public class WebHandlerDecorator implements WebHandler { private final WebHandler delegate; /** * Return the wrapped delegate. */ public WebHandler getDelegate() { return this.delegate; }
可以看到WebHandlerDecorator持有WebHandler对象
总之,我们找到了调用 DispatcherHandher 的地方了,那下一步我们要找 HttpWebHandlerAdapter 是在哪里被装配的,并且webHandler 是是什么时候被注入的,注入的 webHandler 是否就是 DispatcherHandler?
HttpHandlerAutoConfiguration
前面说过的另外一个装配类HttpHandlerAutoConfiguration
@Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DispatcherHandler.class, HttpHandler.class }) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @ConditionalOnMissingBean(HttpHandler.class) @AutoConfigureAfter({ WebFluxAutoConfiguration.class }) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) public class HttpHandlerAutoConfiguration { @Configuration(proxyBeanMethods = false) public static class AnnotationConfig { private final ApplicationContext applicationContext; public AnnotationConfig(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @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; } } }
可以看到这里注入了一个HttpHandler
对象,难道就是HttpWebHandlerAdapter
,继续往下看
首先调用了WebHttpHandlerBuilder.applicationContext(this.applicationContext)方法,点进去看
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) { WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder( context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context); ...... return builder;
可以看到通过context上下文对象通过beanName获取bean来作为参数初始化WebHttpHandlerBuilder对象
/** Well-known name for the target WebHandler in the bean factory. */ public static final String WEB_HANDLER_BEAN_NAME = "webHandler";
而这个beanName正式前面说过的DispatcherHandler
对象
private WebHttpHandlerBuilder(WebHandler webHandler, @Nullable ApplicationContext applicationContext) { Assert.notNull(webHandler, "WebHandler must not be null"); this.webHandler = webHandler; this.applicationContext = applicationContext; }
将WebHttpHandlerBuilder
中的webHandler
属性赋值为DispatcherHandler
对象
接着进入build()方法,整体可以看到返回的HttpHandler对象就是HttpWebHandlerAdapter
public HttpHandler build() { WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters); decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers); HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated); if (this.sessionManager != null) { adapted.setSessionManager(this.sessionManager); } if (this.codecConfigurer != null) { adapted.setCodecConfigurer(this.codecConfigurer); } if (this.localeContextResolver != null) { adapted.setLocaleContextResolver(this.localeContextResolver); } if (this.forwardedHeaderTransformer != null) { adapted.setForwardedHeaderTransformer(this.forwardedHeaderTransformer); } if (this.applicationContext != null) { adapted.setApplicationContext(this.applicationContext); } adapted.afterPropertiesSet(); return (this.httpHandlerDecorator != null ? this.httpHandlerDecorator.apply(adapted) : adapted); }
首先看第一行
//这里的webHandler就是DispatcherHandler对象 WebHandler decorated = new FilteringWebHandler(this.webHandler, this.filters);
public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) { super(handler); this.chain = new DefaultWebFilterChain(handler, filters); }
调用父类的构造方法
private final WebHandler delegate; public WebHandlerDecorator(WebHandler delegate) { Assert.notNull(delegate, "'delegate' must not be null"); this.delegate = delegate; }
此时将delegate赋值为DispatcherHandler对象
接着第二行
//此时入参中的decorated是FilteringWebHandler对象 decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers);
public ExceptionHandlingWebHandler(WebHandler delegate, List<WebExceptionHandler> handlers) { super(delegate); List<WebExceptionHandler> handlersToUse = new ArrayList<>(); handlersToUse.add(new CheckpointInsertingHandler()); handlersToUse.addAll(handlers); this.exceptionHandlers = Collections.unmodifiableList(handlersToUse); }
再次调用父类的构造方法将此对象的父类中delegate属性赋值为FilteringWebHandler对象
接着第三行
HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated);
public HttpWebHandlerAdapter(WebHandler delegate) { super(delegate); }
一样的道理将父类中delegate属性赋值为ExceptionHandlingWebHandler对象
总结一下
HttpWebHandlerAdapter
中delegate保存的是ExceptionHandlingWebHandler
ExceptionHandlingWebHandler
中的delegate保存的是FilteringWebHandler
FilteringWebHandler
中的delegate保存的是DispatcherHandler
到此这篇关于SpringCloud Gateway自动装配实现流程详解的文章就介绍到这了,更多相关SpringCloud Gateway内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringBoot+WebSocket实现IM及时通讯的代码示例
项目中碰到需要及时通讯的场景,使用springboot集成websocket,即可实现简单的及时通讯,本文介绍springboot如何集成websocket、IM及时通讯需要哪些模块、开发和部署过程中遇到的问题、以及实现小型IM及时通讯的代码,需要的朋友可以参考下2023-10-10
最新评论