Spring Cloud Gateway 源碼剖析之配置初始化

點(diǎn)擊上方老周聊架構(gòu)關(guān)注我
一、前言
二、揭秘配置初始化
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
@Configuration
// 執(zhí)行順序注解
// 當(dāng)前注解標(biāo)識(shí)需要在GatewayAutoConfiguration前加載此配置
@AutoConfigureBefore({GatewayAutoConfiguration.class})
public class GatewayClassPathWarningAutoConfiguration {
private static final Log log = LogFactory.getLog(GatewayClassPathWarningAutoConfiguration.class);
private static final String BORDER = "\n\n**********************************************************\n\n";
public GatewayClassPathWarningAutoConfiguration() {
}
@Configuration
// 條件判斷注解
// classpath中不存在org.springframework.web.reactive.DispatcherHandler時(shí)起效,標(biāo)識(shí)項(xiàng)目未導(dǎo)入了spring-boot-starter-webflux包
@ConditionalOnMissingClass({"org.springframework.web.reactive.DispatcherHandler"})
protected static class WebfluxMissingFromClasspathConfiguration {
public WebfluxMissingFromClasspathConfiguration() {
// 當(dāng)前項(xiàng)目未導(dǎo)入了spring-boot-starter-webflux依賴(lài)時(shí),打印警告日志
GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring Webflux is missing from the classpath, which is required for Spring Cloud Gateway at this time. Please add spring-boot-starter-webflux dependency.\n\n**********************************************************\n\n");
}
}
@Configuration
// 條件判斷注解
// classpath中存在org.springframework.web.servlet.DispatcherServlet時(shí)起效,標(biāo)識(shí)項(xiàng)目導(dǎo)入了spring-boot-starter-web包
@ConditionalOnClass(
name = {"org.springframework.web.servlet.DispatcherServlet"}
)
protected static class SpringMvcFoundOnClasspathConfiguration {
public SpringMvcFoundOnClasspathConfiguration() {
// 當(dāng)前項(xiàng)目導(dǎo)入了spring-boot-starter-web依賴(lài)時(shí),打印警告日志
GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.\n\n**********************************************************\n\n");
}
}
}
RoutePredicateHandlerMapping:查找匹配到 Route 并進(jìn)行處理
GatewayProperties:加載網(wǎng)關(guān)配置
RouteDefinitionRouteLocator:創(chuàng)建一個(gè)根據(jù) RouteDefinition 轉(zhuǎn)換的路由定位器
GatewayWebfluxEndpoint:管理網(wǎng)關(guān)的 HTTP API
@Configuration
// 條件注解
// 通過(guò) spring.cloud.gateway.enabled 配置網(wǎng)關(guān)的開(kāi)啟與關(guān)閉
// matchIfMissing = true => 網(wǎng)關(guān)默認(rèn)開(kāi)啟。
@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 {
public GatewayAutoConfiguration() {
}
@Bean
public StringToZonedDateTimeConverter stringToZonedDateTimeConverter() {
return new StringToZonedDateTimeConverter();
}
@Bean
public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) {
return new RouteLocatorBuilder(context);
}
@Bean
@ConditionalOnMissingBean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
return new PropertiesRouteDefinitionLocator(properties);
}
@Bean
@ConditionalOnMissingBean({RouteDefinitionRepository.class})
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
return new InMemoryRouteDefinitionRepository();
}
@Bean
@Primary
public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
}
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> GatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator, @Qualifier("webFluxConversionService") ConversionService conversionService) {
return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties, conversionService);
}
@Bean
@Primary
public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
}
@Bean
public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) {
return new RouteRefreshListener(publisher);
}
@Bean
public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
return new FilteringWebHandler(globalFilters);
}
@Bean
public GlobalCorsProperties globalCorsProperties() {
return new GlobalCorsProperties();
}
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);
}
@Bean
public GatewayProperties gatewayProperties() {
return new GatewayProperties();
}
...
}@Configuration
// 條件判斷注解
// classpath中存在LoadBalancerClient和RibbonAutoConfiguration和DispatcherHandler時(shí)此配置起效
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
// 執(zhí)行順序注解
@AutoConfigureAfter({RibbonAutoConfiguration.class})
@EnableConfigurationProperties({LoadBalancerProperties.class})
public class GatewayLoadBalancerClientAutoConfiguration {
public GatewayLoadBalancerClientAutoConfiguration() {
}
@Bean
// 條件判斷注解
// DI容器中存在LoadBalancerClient類(lèi)型Bean時(shí)起效
@ConditionalOnBean({LoadBalancerClient.class})
@ConditionalOnMissingBean({LoadBalancerClientFilter.class})
public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) {
return new LoadBalancerClientFilter(client, properties);
}
}
@Configuration
@ConditionalOnProperty(
name = {"spring.cloud.gateway.enabled"},
matchIfMissing = true
)
@AutoConfigureBefore({HttpHandlerAutoConfiguration.class})
@AutoConfigureAfter({MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class})
@ConditionalOnClass({DispatcherHandler.class, MeterRegistry.class, MetricsAutoConfiguration.class})
public class GatewayMetricsAutoConfiguration {
public GatewayMetricsAutoConfiguration() {
}
@Bean
@ConditionalOnBean({MeterRegistry.class})
@ConditionalOnProperty(
name = {"spring.cloud.gateway.metrics.enabled"},
matchIfMissing = true
)
public GatewayMetricsFilter gatewayMetricFilter(MeterRegistry meterRegistry) {
return new GatewayMetricsFilter(meterRegistry);
}
}
@Configuration
@AutoConfigureAfter({RedisReactiveAutoConfiguration.class})
@AutoConfigureBefore({GatewayAutoConfiguration.class})
@ConditionalOnBean({ReactiveRedisTemplate.class})
@ConditionalOnClass({RedisTemplate.class, DispatcherHandler.class})
class GatewayRedisAutoConfiguration {
GatewayRedisAutoConfiguration() {
}
@Bean
public RedisScript redisRequestRateLimiterScript() {
DefaultRedisScript redisScript = new DefaultRedisScript();
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("META-INF/scripts/request_rate_limiter.lua")));
redisScript.setResultType(List.class);
return redisScript;
}
@Bean
public ReactiveRedisTemplate<String, String> stringReactiveRedisTemplate(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
RedisSerializer<String> serializer = new StringRedisSerializer();
RedisSerializationContext<String, String> serializationContext = RedisSerializationContext.newSerializationContext().key(serializer).value(serializer).hashKey(serializer).hashValue(serializer).build();
return new ReactiveRedisTemplate(reactiveRedisConnectionFactory, serializationContext);
}
@Bean
@ConditionalOnMissingBean
public RedisRateLimiter redisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate, @Qualifier("redisRequestRateLimiterScript") RedisScript<List<Long>> redisScript, Validator validator) {
return new RedisRateLimiter(redisTemplate, redisScript, validator);
}
}
@Configuration
// 同2
@ConditionalOnProperty(
name = {"spring.cloud.gateway.enabled"},
matchIfMissing = true
)
@AutoConfigureBefore({GatewayAutoConfiguration.class})
@AutoConfigureAfter({CompositeDiscoveryClientAutoConfiguration.class})
@ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class})
@EnableConfigurationProperties
public class GatewayDiscoveryClientAutoConfiguration {
public GatewayDiscoveryClientAutoConfiguration() {
}
@Bean
// 當(dāng)classpath中存在DiscoveryClient起效
@ConditionalOnBean({DiscoveryClient.class})
// 通過(guò)spring.cloud.gateway.discovery.locator.enabled配置注冊(cè)中心查找的開(kāi)啟與關(guān)閉
@ConditionalOnProperty(
name = {"spring.cloud.gateway.discovery.locator.enabled"}
)
public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
}
@Bean
public DiscoveryLocatorProperties discoveryLocatorProperties() {
DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties();
properties.setPredicates(initPredicates());
properties.setFilters(initFilters());
return properties;
}
public static List<PredicateDefinition> initPredicates() {
ArrayList<PredicateDefinition> definitions = new ArrayList();
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(NameUtils.normalizeRoutePredicateName(PathRoutePredicateFactory.class));
predicate.addArg("pattern", "'/'+serviceId+'/**'");
definitions.add(predicate);
return definitions;
}
public static List<FilterDefinition> initFilters() {
ArrayList<FilterDefinition> definitions = new ArrayList();
FilterDefinition filter = new FilterDefinition();
filter.setName(NameUtils.normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class));
String regex = "'/' + serviceId + '/(?<remaining>.*)'";
String replacement = "'/${remaining}'";
filter.addArg("regexp", regex);
filter.addArg("replacement", replacement);
definitions.add(filter);
return definitions;
}
}
三、總結(jié)
歡迎大家關(guān)注我的公眾號(hào)【老周聊架構(gòu)】,Java后端主流技術(shù)棧的原理、源碼分析、架構(gòu)以及各種互聯(lián)網(wǎng)高并發(fā)、高性能、高可用的解決方案。
喜歡的話(huà),點(diǎn)贊、再看、分享三連。

點(diǎn)個(gè)在看你最好看
評(píng)論
圖片
表情



