Flux可以组合多个中间操作,增强代码的复用性及简洁度。
Flux.tranform 示例
Function<Flux<String>, Flux<String>> filterAndMap = f -> f.filter(color ->!color.equals("orange"))
.map(String :: toUpperCase);
Flux.fromIterable(Arrays.asList("blue","green","orange","purple"))
.doOnNext(System.out::println)
.transform(filterAndMap)
.subscribe(d -> System.out.println("Subscriber to Transformed MapAndFilter: " + d));
Flux.tranform是在构造生产者链时进行替换,追踪源码可以发现在.transform处执行了function,.transform返回的就是FluxMap(FluxFilter(FluxPeek(FluxIterable)))。Flux.tranform的实现就是使用组合模式,对重复的中间操作进行了抽取和统一。
Flux#transform
public final <V> Flux<V> transform(Function<? super Flux<T>, ? extends Publisher<V>> transformer) {
if (Hooks.DETECT_CONTEXT_LOSS) {
transformer = new ContextTrackingFunctionWrapper(transformer);
}
return onAssembly(from(transformer.apply(this)));
}
Flux#from
public static <T> Flux<T> from(Publisher<? extends T> source) {
//duplicated in wrap, but necessary to detect early and thus avoid applying assembly
if (source instanceof Flux) {
@SuppressWarnings("unchecked")
Flux<T> casted = (Flux<T>) source;
return casted;
}
//all other cases (including ScalarCallable) are managed without assembly in wrap
//let onAssembly point to Flux.from:
return onAssembly(wrap(source));
}
Flux.compose示例
AtomicInteger ai = new AtomicInteger();
Function<Flux<String>, Flux<String>> filterAndMap = f -> {
if(ai.incrementAndGet() == 1) {
return f.filter(color -> !color.equals("orange"))
.map(String :: toUpperCase);
}
return f.filter(color -> !color.equals("purple"))
.map(String :: toUpperCase);
};
Flux<String> composedFlux =
Flux.fromIterable(Arrays.asList("blue","green","orange","purple"))
.doOnNext(System.out::println)
//编译的时候不会替换transformer,只有在真正产生订阅关系的时候才会transformer这个Function对象所定义 的代码逻辑。
.compose(filterAndMap);
composedFlux.subscribe( d -> System.out.println("Subscriber 1 to Composed MapAndFilter :" + d));
composedFlux.subscribe( d -> System.out.println("Subscriber 2 to Composed MapAndFilter :" + d));
Flux.compose(在3.4.0版本后将会被transformDeferred(Function)替换,本栏目依赖的reactor版本为3.3.11)的实现与Flux.transform不同。Flux.compose返回的是FluxDefer,FluxDefer直接实现SourceProducer,由此可见这是一个源生产者,而并非中间操作。FluxDefer.subscribe时,即在订阅时function函数被执行,这里与Flux.tranform(构建生产者链时,执行function)不同。
Flux#compose
public final <V> Flux<V> compose(Function<? super Flux<T>, ? extends Publisher<V>> transformer) {
//这里把Function->Supplier,定义了一个操作,但没有执行
return defer(() -> transformer.apply(this));
}
Flux#defer
public static <T> Flux<T> defer(Supplier<? extends Publisher<T>> supplier) {
return onAssembly(new FluxDefer<>(supplier));
}
重点的逻辑在FluxDefer#subscribe中
public void subscribe(CoreSubscriber<? super T> actual) {
Publisher<? extends T> p;
try {
//Function的执行在这里
p = Objects.requireNonNull(supplier.get(),
"The Publisher returned by the supplier is null");
}
catch (Throwable e) {
Operators.error(actual, Operators.onOperatorError(e, actual.currentContext()));
return;
}
//from(p)构建完整的生产者链FluxMap(FluxFilter(FluxPeek(FluxIterable)))
//FluxMap(FluxFilter(FluxPeek(FluxIterable))).subscribe(actual)
from(p).subscribe(actual);
}
FluxDefer使用函数对操作进行了封装,在真正需要时触发执行函数,有一丝延迟加载的味道,在业务项目中这种设计思路可以借鉴。