Reactor3 源码解析十六: Flux.transform & Flux.compose源码剖析

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使用函数对操作进行了封装,在真正需要时触发执行函数,有一丝延迟加载的味道,在业务项目中这种设计思路可以借鉴。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值