咱们从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。
@Override
public 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;
}
整体流程
发表回复