Spring5中Reactor编程的Mono与Flux类源码解读

Spring5的函数式编程使用了ProjectReactor工程的类,使用最为多的就是Mono和Flux类型,其中Mono是针对0到1个元素进行操作,Flux是针对多个元素进行操作。要使用这两个类前提是自己要有jdk8,Lambda,函数式编程的基础,否则请先学习了以上知识再来接触Spring5的Mono和FLux。

我们针对Mono类的一行代码,来进行源码分析与讲解。代码如下:

Mono.just("hello").subscribe(System.out::println);
这行代码是生成有一个元素的Mono类,并打印“hello”字符串。

首先,通过Mono.just()方法生成了Mono类

	public static <T> Mono<T> just(T data) {
		return onAssembly(new MonoJust<>(data));
	}
以上代码可以看到是创建了一个MonoJust类型,这个类和Mono,FLux类型一样在reactor-core包中,其实Mono的每个方法都会对应生成一个Mono的子类,其子类很多,如下:

截图只是列举了一部分,Mono采用这种每个方法都生成一个类的方式是与jdk8中的Stream流水线的最大区别,目的是为了重用任意阶段的结果,且其所有子类都实现了Mono类的方法:
public abstract void subscribe(CoreSubscriber<? super T> actual);
这个方法我们后面会讲,它的作用就是处理后面的函数式的逻辑。


在返回MonoJust类型后,我们调用了subscribe(System.out::println)方法,这个方法在Mono类有具体实现,方法如下:

	public final Disposable subscribe(Consumer<? super T> consumer) {
		Objects.requireNonNull(consumer, "consumer");
		return subscribe(consumer, null, null);
	}
这个方法是所有Mono的子类执行subscribe(CoreSubscriber<? super T> actual)方法的入口,我们进入看下,执行到了如下方法:

	public final Disposable subscribe(
			@Nullable Consumer<? super T> consumer,
			@Nullable Consumer<? super Throwable> errorConsumer,
			@Nullable Runnable completeConsumer,
			@Nullable Consumer<? super Subscription> subscriptionConsumer) {
		return subscribeWith(new LambdaMonoSubscriber<>(consumer, errorConsumer,
				completeConsumer, subscriptionConsumer));
	}
我们看到有四个参数,根据字面意思即可理解,lambda表达式是第一个参数consumer,可以看到执行Lambda的方法时候创建了一个类型LambdaMonoSubscriber,这个类型封装了封装了四个参数。

后面进入此方法:
	@Override
	public final void subscribe(Subscriber<? super T> actual) {
		onLastAssembly(this).subscribe(Operators.toCoreSubscriber(actual));
	}
这个方法是重写了父类Publisher的suscribe方法,我们看到代码做了类型转换,通过类型转换就转换为了可以调用MonoJust中的subscribe方法了,MonoJust总的subscribe方法如下,所有的Mono子类都重写了此方法:
	@Override
	public void subscribe(CoreSubscriber<? super T> actual) {
		actual.onSubscribe(Operators.scalarSubscription(actual, value));
	}

然后通过LambdaMonoSubscriber的onSubscribe方法在调用Operators的request方法,再调用此LambdaMonoSubscriber的onNext方法,最后调用了我们自己写的Lambda表达式,如下:

	@Override
	public final void onNext(T x) {
		Subscription s = S.getAndSet(this, Operators.cancelledSubscription());
		if (s == Operators.cancelledSubscription()) {
			Operators.onNextDropped(x, Context.empty());
			return;
		}
		if (consumer != null) {
			try {
				consumer.accept(x);
			}
consumer就是我们传入进来的Lambda表达式,这个方法继承自Suscriber类
通过这种方式,Publisher发送的subscribe就被Subscriber类消费掉了。其实全程都是一个单线程的操作。借鉴了消费订阅模式。

关于Mono的方法很多,在此只是举了一个简单的例子,其他的方法也可以通过类似的方式去研究。





猜你喜欢

转载自blog.csdn.net/lz710117239/article/details/80603249