响应式编程之Mono使用手册

响应式编程整体流程分为两个方向:构建方向以及订阅方向。

构建方向:针对不同方法生成与之对应的Mono子类实例。

Mono静态方法构建发布者 -> Mono中间操作符MonoOperator -> 订阅subscribe

订阅方向:逆向找到最初发布者 Publisher后,经过各个中间操作符MonoOperator中间操作,实现从上往下依次订阅。

为了便于阅读首先需要明确几个概念:

当前Mono实例:指触发新建Mono实例的调用方。

新建Mono实例:指正构建的Mono实例,由当前Mono实例触发。

实际消息订阅:指被封装为Subscription之前的消息。

中间消息订阅:中间操作符对流转中的数据实施的操作。


1.标准发布<->订阅流程

在响应式编程中

Mono.defer(() -> Mono.just(12)).subscribe(new Subscriber<Integer>() {
    @Override
    public void onSubscribe(Subscription s) {
        System.out.println("s");
        s.request(10);
    }
    @Override
    public void onNext(Integer integer) {
        System.out.println("onNext");
    }
    @Override
    public void onError(Throwable t) {
        System.out.println("onError");
    }
    @Override
    public void onComplete() {
        System.out.println("onComplete");
    }
});

1.1.发布者Publisher

通过Mono中静态方法构建发布者实例。

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}

发布订阅模式理论是Publisher发布消息,Subscriber负责订阅/消费消息,但是在响应式编程中直观上Publisher发布消息对象直接是Subscriber/Consumer。


1.2.订阅者Subscriber

响应式编程中订阅者存在两种形式:CoreSubscriber & StrictSubscriber。两者的区别主要来自Publisher发布的消息类型:接口Consumer or 接口Subscriber。StrictSubscriber通常是指匿名内部类方式定义订阅过程,接口Consumer 定义的订阅过程最终以LambdaMonoSubscriber方式存在。

public interface Subscriber<T> {
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}

响应式编程中提供了一个核心类Operators。很多Mono子类在subscrib之时将实际消息订阅抽象化为ScalarSubscription,并且由ScalarSubscription回调Subscriber#onNext方法。

public interface CoreSubscriber<T> extends Subscriber<T> {
	void onSubscribe(Subscription s);
}

CoreSubscriber & StrictSubscriber两者有个区别:StrictSubscriber同时实现了接口Subscription。


1.2.1.消息订阅~Subscription

响应式编程中Subscriber内部会将实际消息订阅封装为Subscription。

A Subscription represents a one-to-one lifecycle of a Subscriber subscribing to a Publisher。一个订阅者只可能调用一次。

public interface Subscription {
    public void request(long n);//正数
}

响应式编程中在触发当前方法之前是不会发送任何事件的。


1.3.中间操作符MonoOperator

MonoOperator官方介绍即为被修饰的Publisher。通常是通过Mono中非静态方法创建相关MonoOperator的实例。例如:MonoFlatMap、MonoPeekFuseable【doOnNext】、MonoPeekTerminal【doOnError】等常用类型。

通常MonoOperator兼具抽象类InternalMonoOperator、接口OptimizableOperator特性。


1.3.1.OptimizableOperator

A common interface of operator in Reactor which adds contracts around subscription optimizations。

interface OptimizableOperator<IN, OUT> extends CorePublisher<IN> {
	CoreSubscriber<? super OUT> subscribeOrReturn(CoreSubscriber<? super IN> actual) throws Throwable;
	CorePublisher<? extends OUT> source();
	OptimizableOperator<?, ? extends OUT> nextOptimizableSource();
}

针对MonoOperator功能新增的一些规范,其中subscribeOrReturn:Allow delegation of the subscription by returning a CoreSubscriber, or force subscription encapsulation【封装】 by returning null. This can be used in conjunction【结合】 with nextOptimizableSource() to perform subscription in a loop instead of by recursion。


1.3.2.InternalMonoOperator

除了实现抽象类MonoOperator,剩下的是对接口OptimizableOperator的简单实现。

public abstract class InternalMonoOperator<I, O> extends MonoOperator implements OptimizableOperator<O, I>{
   
    OptimizableOperator<?, I> optimizableOperator;

   protected InternalMonoOperator(Mono<? extends I> source) {
		super(source);//source是指当前Momo实例
        if (source instanceof OptimizableOperator) {
			OptimizableOperator<?, I> optimSource = (OptimizableOperator<?, I>) source;
			this.optimizableOperator = optimSource;
		}
		else {
			this.optimizableOperator = null;
		}
		...
	}
    //接口OptimizableOperator定义的方法
    @Nullable
	public abstract CoreSubscriber<? super I> subscribeOrReturn(CoreSubscriber<? super O> actual);
    //接口OptimizableOperator定义的方法
	@Override
	public final CorePublisher<? extends I> source() {
		return source;
	}
    //接口OptimizableOperator定义的方法
	@Override
	public final OptimizableOperator<?, ? extends I> nextOptimizableSource() {
		return optimizableOperator;
	}
}

2.发布订阅模式标准流程源码分析

这种模式下订阅者Subscriber通过匿名内部类方式实现。Subscriber类型最后通过StrictSubscriber持有具体的实际订阅消息。

public abstract class Mono<T> implements CorePublisher<T> {
    public final void subscribe(Subscriber<? super T> actual) {
        // 获取发布者构建过程中最后一个发布者
        CorePublisher publisher = Operators.onLastAssembly(this);
        // 判定Subscriber的类型 ~ StrictSubscriber
        CoreSubscriber subscriber = Operators.toCoreSubscriber(actual);
        try {
            if (publisher instanceof OptimizableOperator) {//标准流程中不满足条件
                ...
            }
            publisher.subscribe(subscriber);//第一步
        }catch (Throwable e) {
            Operators.reportThrowInSubscribe(subscriber, e);
            return;
        }
    } 
}

但是没有中间操作符MonoOperator所以对于Subscriber并非接口OptimizableOperator的子类。

final class MonoDefer<T> extends Mono<T> implements SourceProducer<T> {

    @SuppressWarnings("unchecked")
    public void subscribe(CoreSubscriber<? super T> actual) {
        Mono<? extends T> p;
        try {
            p = Objects.requireNonNull(supplier.get(), "The Mono returned by the supplier is null");
        }catch (Throwable e) {//异常处理
            Operators.error(actual, Operators.onOperatorError(e, actual.currentContext()));
            return;
        }
        p.subscribe(actual);//第二步:返回的Mono为MonoJust
    }
}
final class MonoJust<T> {
    @Override
    public void subscribe(CoreSubscriber<? super T> actual) {
        // 第三步:将实际订阅消息封装为Subscription
        actual.onSubscribe(Operators.scalarSubscription(actual, value));
    }
}

 上述类Operators将实际订阅消息抽象化为ScalarSubscription。

final class StrictSubscriber<T> implements Scannable, CoreSubscriber<T>, Subscription {

    final Subscriber<? super T> actual;
    volatile Subscription s;

    @Override
    public void onSubscribe(Subscription s) {//s是指由Operaters构建的ScalarSubscription
        if (Operators.validate(this.s, s)) {
            //this是指当前实例StrictSubscriber
            actual.onSubscribe(this);//第四步:调用用户自定义的onSubscribe逻辑
            if (Operators.setOnce(S, this, s)) {//第六步:将参数s赋值给变量S,以及实例变量s
                long r = REQUESTED.getAndSet(this, 0L);
                if (r != 0L) {
                    // 回调 ScalarSubscription的request方法
                    s.request(r);
                }
            }
        }
    }

    @Override
    public void onNext(T t) {//第七步:由ScalarSubscription的request方法负责回调该 onNext 方法
        if (WIP.get(this) == 0 && WIP.compareAndSet(this, 0, 1)) {
            actual.onNext(t);//调用用户自定义的onNext逻辑
            ...
        }
    }

    @Override
    public void request(long n) {//第五步:由用户onSubscribe逻辑内部通过Subscription回调
        if (n <= 0) {
            cancel();
            onError(new IllegalArgumentException("§3.9 violated: positive request amount required but it was " + n));
            return;
        }
        Subscription a = s;//截止当前变量s为null
        if (a != null) {
            a.request(n);
        }else {
            Operators.addCap(REQUESTED, this, n);
            a = s;//截止当前变量s为null
            if (a != null) {
                long r = REQUESTED.getAndSet(this, 0L);
                if (r != 0L) {
                    a.request(n);
                }
            }
        }
    }
}

3. 发布订阅源码分析~Consumer类型的Subscriber

public static void subscriber(){
    Mono.defer(() -> Mono.just(12))
        .subscribe(item -> System.out.println(item));
}

Consumer类型的Subscriber区别于StrictSubscriber,最后是通过LambdaMonoSubscriber持有具体的实际订阅消息。

final class LambdaMonoSubscriber<T> implements InnerConsumer<T>, Disposable {

        final Consumer<? super T>            consumer;// Consumer类型的消息订阅
        final Consumer<? super Throwable>    errorConsumer;
        final Runnable                       completeConsumer;
        final Consumer<? super Subscription> subscriptionConsumer;
        final Context                        initialContext;

        @Override
        public final void onSubscribe(Subscription s) {
                if (Operators.validate(subscription, s)) {
                        this.subscription = s;
                        if (subscriptionConsumer != null) {// 需要用户显式订阅该subscriptionConsumer
                                try {
                                        subscriptionConsumer.accept(s);
                                }catch (Throwable t) {
                                        Exceptions.throwIfFatal(t);
                                        s.cancel();
                                        onError(t);
                                }
                        }
                        else {//默认方式,s是指由Operaters构建的ScalarSubscription
                                s.request(Long.MAX_VALUE);
                        }

                }
        }

        @Override
        public final void onNext(T x) {//由ScalarSubscription的request方法负责回调该
                Subscription s = S.getAndSet(this, Operators.cancelledSubscription());
                if (s == Operators.cancelledSubscription()) {
                        Operators.onNextDropped(x, this.initialContext);
                        return;
                }
                if (consumer != null) {
                        try {
                                consumer.accept(x);//调用用户自定义的Consumer类型的消息订阅
                        }catch (Throwable t) {
                                Operators.onErrorDropped(t, this.initialContext);
                                return;
                        }
                }
                if (completeConsumer != null) {
                        try {
                                completeConsumer.run();
                        }catch (Throwable t) {
                                Operators.onErrorDropped(t, this.initialContext);
                        }
                }
        }
}

4.中间操作符 MonoOperator 之发布订阅源码分析

public static void op(){
        Mono.defer(() -> Mono.just(12))
                // MonoFlatMap
                .flatMap(item -> Mono.just(item + 100))
                // MonoDoOnEachFuseable
                .doOnEach(item -> System.out.println(item))
                .subscribe(item -> System.out.println(" end = "+ item));
    }

4.1.操作符MonoOperator构建流程

public final class MonoFlatMap{
    final Function<? super T, ? extends Mono<? extends R>> mapper;

    MonoFlatMap(Mono<? extends T> source,Function<? super T, ? extends Mono<? extends R>> mapper) {
        super(source);//source 为 MonoDefer
        this.mapper = Objects.requireNonNull(mapper, "mapper");//当前操作符具体逻辑
    }
}

final class MonoDoOnEachFuseable<T> extends InternalMonoOperator<T, T> implements Fuseable {

    final Consumer<? super Signal<T>> onSignal;

    MonoDoOnEachFuseable(Mono<? extends T> source, Consumer<? super Signal<T>> onSignal) {
        super(source);//source 为 MonoFlatMap
        this.onSignal = Objects.requireNonNull(onSignal, "onSignal");//当前操作符具体逻辑
    }

    @Override
    public CoreSubscriber<? super T> subscribeOrReturn(CoreSubscriber<? super T> actual) {
        //actual:实际消息订阅之LambdaMonoSubscriber,返回其内部类DoOnEachFuseableSubscriber
        return FluxDoOnEach.createSubscriber(actual, onSignal, true, true);
    }
}

4.2.订阅者Subscriber反向定位Publisher

public abstract class Mono<T> implements CorePublisher<T> {
    // actual:LambdaMonoSubscriber
    public final void subscribe(Subscriber<? super T> actual) {
        // 获取发布者构建过程中最后一个发布者 ~ MonoDoOnEachFuseable
        CorePublisher publisher = Operators.onLastAssembly(this);
        //subscriber:LambdaMonoSubscriber
        CoreSubscriber subscriber = Operators.toCoreSubscriber(actual);
        try {
            //中间操作符MonoOperator当然实现了接口OptimizableOperator
            if (publisher instanceof OptimizableOperator) {
                OptimizableOperator operator = (OptimizableOperator) publisher;
                while (true) {
                    subscriber = operator.subscribeOrReturn(subscriber);
                    if (subscriber == null) {
                        // null means "I will subscribe myself", returning...
                        return;
                    }

                    OptimizableOperator newSource = operator.nextOptimizableSource();
                    if (newSource == null) {//向上查找直到发现是Publisher
                        publisher = operator.source();
                        break;
                    }
                    operator = newSource;
                }
            }
            // MonoDefer 触发整个订阅流程
            publisher.subscribe(subscriber);
        }catch (Throwable e) {
            Operators.reportThrowInSubscribe(subscriber, e);
            return;
        }
    } 
}
  1. 通过MonoDoOnEachFuseable#subscribeOrReturn返回DoOnEachFuseableSubscriber,其中subscriber为LambdaMonoSubscriber。
  2. MonoDoOnEachFuseable#nextOptimizableSource返回MonoFlatMap。
  3. 再次循环,通过MonoFlatMap#subscribeOrReturn返回其内部类FlatMapMain,其中subscriber为DoOnEachFuseableSubscriber。
  4. FlatMapMain#nextOptimizableSource由于FlatMap前一个Mono实例非MonoOperator所以返回null,紧接着通过MonoFlatMap获取到属性source指向的MonoDefer。

5.错误处理

执行某个Mono相关的消费逻辑时如果出现异常,则查看该目标方法调用是否存在try..catch处理异常,并且在catch内部是否存在Operators.error处理异常信息,异常处理会终止后续流程,只会根据Operators#onError方法一直往下游订阅。某些Mono如MonoDoOnEach也是异常处理的必经之路。

只要出现异常就不会执行后续正常逻辑,而是一直调用下游全部Operators#onError方法,即error订阅链跟正常订阅链互斥。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值