SpringCloud Gateway自動裝配實現(xiàn)流程詳解
啟動依賴
找到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的核心依賴,找到依賴包,看到如下結(jié)構(gòu)
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(); }
有點聯(lián)想到DispatcherSerlvet
,類似前端控制器
public class DispatcherHandler implements WebHandler, PreFlightRequestHandler, ApplicationContextAware {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->
可以看到DispatcherHandler
實現(xiàn)了WebHandler接口并實現(xiàn)了其中的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
應(yīng)該就是核心的處理方法,此時又有疑問,該方法什么時候被調(diào)用,被誰調(diào)用的
官方文檔上提到WebHandler
上面還有一個關(guān)鍵的 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 來調(diào)用 WebHandler (請求由下往上),那DispatcherHandler
作為 WebHandler
的一個實現(xiàn),也很有可能會被HttpHandler
的具體實現(xiàn)所持有。
通過HttpHandler
的實現(xiàn)類不難找到HttpWebHandlerAdapter
就是我們要找的,并且持有一個WebHandher
對象,當然也可以通過斷點調(diào)試找到。
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對象
總之,我們找到了調(diào)用 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
,繼續(xù)往下看
首先調(diào)用了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來作為參數(shù)初始化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); }
調(diào)用父類的構(gòu)造方法
private final WebHandler delegate; public WebHandlerDecorator(WebHandler delegate) { Assert.notNull(delegate, "'delegate' must not be null"); this.delegate = delegate; }
此時將delegate賦值為DispatcherHandler對象
接著第二行
//此時入?yún)⒅械膁ecorated是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); }
再次調(diào)用父類的構(gòu)造方法將此對象的父類中delegate屬性賦值為FilteringWebHandler對象
接著第三行
HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated);
public HttpWebHandlerAdapter(WebHandler delegate) { super(delegate); }
一樣的道理將父類中delegate屬性賦值為ExceptionHandlingWebHandler對象
總結(jié)一下
HttpWebHandlerAdapter
中delegate保存的是ExceptionHandlingWebHandler
ExceptionHandlingWebHandler
中的delegate保存的是FilteringWebHandler
FilteringWebHandler
中的delegate保存的是DispatcherHandler
到此這篇關(guān)于SpringCloud Gateway自動裝配實現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)SpringCloud Gateway內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringCloud Gateway動態(tài)路由配置詳解
- SpringCloud Gateway路由組件詳解
- SpringCloud Gateway的路由,過濾器和限流解讀
- SpringCloud Gateway網(wǎng)關(guān)功能介紹與使用
- SpringCloud Gateway實現(xiàn)限流功能詳解
- SpringCloud服務(wù)網(wǎng)關(guān)Gateway的使用教程詳解
- SpringCloud中Gateway的使用教程詳解
- SpringCloud超詳細講解微服務(wù)網(wǎng)關(guān)Gateway
- SpringCloud Gateway動態(tài)轉(zhuǎn)發(fā)后端服務(wù)實現(xiàn)過程講解
相關(guān)文章
Android讀取本地或網(wǎng)絡(luò)圖片并轉(zhuǎn)換為Bitmap
這篇文章主要為大家詳細介紹了Android讀取本地或網(wǎng)絡(luò)圖片,并轉(zhuǎn)換為Bitmap,感興趣的小伙伴們可以參考一下2016-08-08SpringBoot+WebSocket實現(xiàn)IM及時通訊的代碼示例
項目中碰到需要及時通訊的場景,使用springboot集成websocket,即可實現(xiàn)簡單的及時通訊,本文介紹springboot如何集成websocket、IM及時通訊需要哪些模塊、開發(fā)和部署過程中遇到的問題、以及實現(xiàn)小型IM及時通訊的代碼,需要的朋友可以參考下2023-10-10如何利用Spring?Boot?監(jiān)控?SQL?運行情況
這篇文章主要介紹了如何利用Spring?Boot監(jiān)控SQL運行情況,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07