咱们从spring.factories开始,次要是GatewayAutoConfiguration,这里次要加载CompositeRouteDefinitionLocator、RouteDefinitionRouteLocator、FilteringWebHandler、RoutePredicateHandlerMapping、RouteRefreshListener、CachingRouteLocator等。
RouteLocator和RouteDefinitionLocator的作用在上一篇曾经提过了,FilteringWebHandler、RoutePredicateHandlerMapping这两个等调用的时候讲,这边先晓得他们会在这里加载。咱们次要看看RouteRefreshListener和CachingRouteLocator。
RouteRefreshListener
RouteRefreshListener实现了ApplicationListener接口,所以他会调用onApplicationEvent办法,在合乎某些条件下,会调用reset办法,这个思路和zuul是一样的。所以动静的刷新也能够调用他的事件来触发。
public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof InstanceRegisteredEvent) { reset(); } else if (event instanceof ParentHeartbeatEvent) { ParentHeartbeatEvent e = (ParentHeartbeatEvent) event; resetIfNeeded(e.getValue()); } else if (event instanceof HeartbeatEvent) { HeartbeatEvent e = (HeartbeatEvent) event; resetIfNeeded(e.getValue()); }}
咱们看看reset办法,他其实就是公布了一个RefreshRoutesEvent事件。
private void reset() { this.publisher.publishEvent(new RefreshRoutesEvent(this));}
CachingRouteLocator
CachingRouteLocator就是用来接管RefreshRoutesEvent事件的,他实现了ApplicationListener<RefreshRoutesEvent>接口。咱们看看他的onApplicationEvent办法。
public void onApplicationEvent(RefreshRoutesEvent event) { try { fetch().collect(Collectors.toList()).subscribe(list -> Flux.fromIterable(list) .materialize().collect(Collectors.toList()).subscribe(signals -> { applicationEventPublisher .publishEvent(new RefreshRoutesResultEvent(this)); cache.put(CACHE_KEY, signals); }, throwable -> handleRefreshError(throwable))); } catch (Throwable e) { handleRefreshError(e); }}
他先会调用fetch办法,这里实际上就是调用CompositeRouteLocator#getRoutes,最初再调用RouteDefinitionRouteLocator#getRoutes。
private Flux<Route> fetch() { return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);}
RouteDefinitionRouteLocator#getRoutes
这个办法能够看到他是获取RouteDefinition的汇合,而后再调用convertToRoute办法,在这个办法里,把RouteDefinition转为Route。
@Overridepublic Flux<Route> getRoutes() { Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions() .map(this::convertToRoute); // 其余略}
RouteDefinitionRouteLocator#convertToRoute
在这里把RouteDefinition转为Route,次要是解析Predicate和GatewayFilter,咱们在上一篇曾经晓得了他会通过工厂类来解决。combinePredicates办法就是解决Predicate的,getFilters是解决Filter的。
private Route convertToRoute(RouteDefinition routeDefinition) { AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition); List<GatewayFilter> gatewayFilters = getFilters(routeDefinition); return Route.async(routeDefinition).asyncPredicate(predicate) .replaceFilters(gatewayFilters).build();}
RouteDefinitionRouteLocator#combinePredicates
在这里就是把RouteDefinition的predicate转为Route须要的Predicate。这里首先会创立一个Predicate,而后再把残余的合并,造成了一个left、right的构造。结构图在上一篇曾经说过了。
lookup办法就是通过工厂类创立Predicate的中央。
private AsyncPredicate<ServerWebExchange> combinePredicates( RouteDefinition routeDefinition) { List<PredicateDefinition> predicates = routeDefinition.getPredicates(); if (predicates == null || predicates.isEmpty()) { // this is a very rare case, but possible, just match all return AsyncPredicate.from(exchange -> true); } // 创立第一个Predicate AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition, predicates.get(0)); // 把残余的进行合并 for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate); predicate = predicate.and(found); } return predicate;}
RouteDefinitionRouteLocator#lookup
这个办法里,首先先通过配置的名称,获取对应的RoutePredicateFactory,而后组装config信息,最初通过factory.applyAsync创立Predicate。
private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) { RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName()); if (factory == null) { throw new IllegalArgumentException( "Unable to find RoutePredicateFactory with name " + predicate.getName()); } if (logger.isDebugEnabled()) { logger.debug("RouteDefinition " + route.getId() + " applying " + predicate.getArgs() + " to " + predicate.getName()); } // @formatter:off Object config = this.configurationService.with(factory) .name(predicate.getName()) .properties(predicate.getArgs()) .eventFunction((bound, properties) -> new PredicateArgsEvent( RouteDefinitionRouteLocator.this, route.getId(), properties)) .bind(); // @formatter:on return factory.applyAsync(config);}
RouteDefinitionRouteLocator#getFilters
这个是解决Filter的中央,他次要是通过loadGatewayFilters办法来获取对应的Filter。
private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) { List<GatewayFilter> filters = new ArrayList<>(); // TODO: support option to apply defaults after route specific filters? if (!this.gatewayProperties.getDefaultFilters().isEmpty()) { filters.addAll(loadGatewayFilters(DEFAULT_FILTERS, new ArrayList<>(this.gatewayProperties.getDefaultFilters()))); } if (!routeDefinition.getFilters().isEmpty()) { filters.addAll(loadGatewayFilters(routeDefinition.getId(), new ArrayList<>(routeDefinition.getFilters()))); } AnnotationAwareOrderComparator.sort(filters); return filters;}
RouteDefinitionRouteLocator#loadGatewayFilters
这个设计形式跟下面相似,也是通过配置信息的名称,获取对应的GatewayFilterFactory,而后封装configuration信息,通过factory.apply创立一个Filter。
List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) { ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size()); for (int i = 0; i < filterDefinitions.size(); i++) { FilterDefinition definition = filterDefinitions.get(i); GatewayFilterFactory factory = this.gatewayFilterFactories .get(definition.getName()); if (factory == null) { throw new IllegalArgumentException( "Unable to find GatewayFilterFactory with name " + definition.getName()); } if (logger.isDebugEnabled()) { logger.debug("RouteDefinition " + id + " applying filter " + definition.getArgs() + " to " + definition.getName()); } // @formatter:off Object configuration = this.configurationService.with(factory) .name(definition.getName()) .properties(definition.getArgs()) .eventFunction((bound, properties) -> new FilterArgsEvent( // TODO: why explicit cast needed or java compile fails RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties)) .bind(); // @formatter:on // some filters require routeId // TODO: is there a better place to apply this? if (configuration instanceof HasRouteId) { HasRouteId hasRouteId = (HasRouteId) configuration; hasRouteId.setRouteId(id); } GatewayFilter gatewayFilter = factory.apply(configuration); if (gatewayFilter instanceof Ordered) { ordered.add(gatewayFilter); } else { ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1)); } } return ordered;}