反应式编程的特点
要知道反应式编程,首先要明白它和我们普通的编程方式有什么区别。我们开发普通应用程序的时候,通常都是一段代码执行一段代码的进行,程序运行的时候,上一段代码运行完成之前,下一段代码是不会运行的。例如:
public static void main(String[] args) {
String words = "";
words += "Hello ";
words += "World!";
System.out.println(words);
}
而反应式编程则与之不同,例如:
public static void main(String[] args) {
Mono.just("")
.map(a -> "Hello ")
.map(b -> b + "World!")
.subscribe(System.out::println);
}
反应式编程中运行时的数据处理就像一个流水线一样,数据从管道入口流入,出口流出。管道中有几个处理的节点对数据进行加工处理。数据是源源不断的进行处理的,前面的数据处理完马上进入下一个环节,不会等到所有数据处理完才进去下一环节。
反应式编程规范
反应式规范其实非常简单,总结起来就4个接口:
- Publisher接口:这个接口顾名思义,可以称它为发布者接口。它声明了一个接口方法subscribe(),订阅者通过这个方法向发布者发起订阅。之后订阅者就可以接收到来自发布者发布的消息或者事件。
- Subscriber接口:这个接口,就是上面提到的订阅者接口,订阅者订阅发布者的消息之后,发布者就通过这个接口中定义的接口方法来发布事件。
- Subscription接口:这个接口在上面的Subscriber接口中有涉及,它是一个用于订阅者和发布者进行沟通的一个接口。
- Processor接口:通过下面的定义就能看出它是一个发布者接口和订阅者接口的组合接口,类似于流水线中的一个处理节点。当它作为订阅者,接受来自上游发布者的消息进行处理,然后作为发布者,将处理之后的消息发布给下游的其他订阅者。
以下是上述4个接口的定义以及接口方法的详细解释:
public interface Publisher<T> {
/**
* 订阅接口,订阅者通过调用发布者的这个接口来订阅消息
* @param subscriber 订阅者
*/
void subscribe(Subscriber<? super T> subscriber);
}
public interface Subscriber<T> {
/**
* 发布者向订阅者发布消息前调用的接口,通过传入一个Subscription对象,
* 订阅者可以用来和发布者进行沟通,例如我想要接收多少消息,详情可以参考
* Subscription的接口定义
* @param subscription Subscription对象
*/
void onSubscribe(Subscription subscription);
/**
* 发布者发布的每个消息,就是通过这个方法传递给订阅者
* @param item 消息
*/
void onNext(T item);
/**
* 当发布者有任何错误,就会调用这个方法通知订阅者
* @param ex 异常信息
*/
void onError(Throwable ex);
/**
* 当发布者消息发送完毕,就调用这个接口通知订阅者
*/
void onComplete();
}
public interface Subscription {
/**
* 订阅者调用这个方法是通知发布者我想要接受多少数据,
* 以免消息过多订阅者无法及时处理完成,当这些消息都
* 处理完成之后,订阅者可以再次调用该方法请求更多的数据
* @param n 数据量
*/
void request(long n);
/**
* 当订阅者对消息不再感兴趣不希望发布者发送消息给自己时,
* 通过调用这个接口来通知发布者不再发送消息,并取消订阅
*/
void cancel();
}
/**
* 这个接口是发布者和订阅者的组合接口,直接参考发布者和订阅者接口的接口方法即可
* @param <T> 订阅者
* @param <R> 发布者
*/
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
通过以上4个接口,很容易就能构建出一个以Publisher作为开始的数据处理流水线,让数据通过0个或多个Processor,然后将最终结果传递给Subscriber。
Reactor项目就是这个反应式规范的一个实现,它提供了一组用于组装反应式流的函数式API,这个我们将在下篇文章中进行探讨。
最后,欢迎大家在评论区进行交流探讨,共同进步!