Spring-Cloud-Gateway-03-网关自动装配



系列文章

Spring-Cloud-Gateway-01-网关基本概念

Spring-Cloud-Gateway-02-请求调用基本流程

Spring-Cloud-Gateway-03-网关自动装配

Spring-Cloud-Gateway-04-HttpWebHandlerAdapter到DispatcherHandler调用流程

Spring-Cloud-Gateway-05-请求到HttpWebHandlerAdapter的调用链路

Spring-Cloud-Gateway-06-DispatcherHandler调用解析

Spring-Cloud-Gateway-07-GatewayFilterChain的执行过程

Spring-Cloud-Gateway-08-路由的自动装配与加载流程

Spring-Cloud-Gateway-09-动态路由与自动刷新



启动依赖

找到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的核心依赖,找到依赖包,看到如下结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3bENhB1o-1665995473323)(C:\Users\mojiahao\AppData\Roaming\Typora\typora-user-images\image-20221014145321438.png)]

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.GatewayReactiveOAuth2AutoConfiguration

org.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分别是在之前和之后加载

其中HttpHandlerAutoConfigurationWebFluxAutoConfiguration算是比较重要的装配类


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 {

可以看到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 {

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值