
Mono 是响应式流中代表“最多一个异步结果”的不可变发布者(Publisher),而 MonoSink 是创建自定义 Mono 时用于主动发出信号(success/error/complete)的单次写入工具,二者处于不同抽象层级:前者是声明式数据容器,后者是命令式信号控制入口。
mono 是响应式流中代表“最多一个异步结果”的不可变发布者(publisher),而 monosink 是创建自定义 mono 时用于**主动发出信号**(success/error/complete)的单次写入工具,二者处于不同抽象层级:前者是声明式数据容器,后者是命令式信号控制入口。
在 Project Reactor 中,Mono
✅ Mono:声明式、惰性、不可变的“承诺”
Mono
- ✅ 惰性求值:Mono.just("data")、Mono.fromCallable(...) 等工厂方法仅构建流定义,不触发计算;
- ✅ 不可变性:所有操作符(如 .map()、.flatMap()、.onErrorResume())均返回全新 Mono 实例,原始对象不受影响;
- ✅ 声明式组合:开发者通过链式调用表达“做什么”,而非“如何做”。
Mono<string> userMono = userRepository.findById(123)
.map(User::getName)
.filter(name -> name.length() > 2)
.switchIfEmpty(Mono.just("Anonymous"));
// 此时:无数据库查询、无字符串处理、无判断——一切待订阅才发生</string>
✅ MonoSink:命令式、一次性、可变的“信号发射器”
MonoSink
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ⚠️ 仅限 Mono.create() 使用:必须在 Consumer
> 回调内调用; - ⚠️ 严格单次语义:sink.success(value) 或 sink.error(e) 只能调用一次;重复调用将抛出 IllegalStateException;
- ⚠️ 线程安全桥接:常用于封装回调式 API(如 Netty、RxJava 1.x、老式 CompletableFuture 回调),将多线程通知安全转为响应式信号。
// ✅ 正确:使用 MonoSink 封装异步回调
Mono<user> legacyApiMono = Mono.create(sink -> {
legacyUserService.findById(123, new Callback<user>() {
@Override
public void onSuccess(User user) {
sink.success(user); // ✅ 发出单个值并完成
}
@Override
public void onFailure(Exception e) {
sink.error(e); // ✅ 发出错误并终止
}
});
});
// ❌ 错误示例(编译可通过,但运行时异常)
Mono<string> badMono = Mono.create(sink -> {
sink.success("first"); // ✅ OK
sink.success("second"); // ❌ IllegalStateException: sink has already been completed
});</string></user></user>
? 关键对比总结
| 维度 | Mono |
MonoSink |
|---|---|---|
| 角色 | 响应式数据流(Publisher) | 创建 Mono 时的信号控制句柄(仅在 create() 内可用) |
| 生命周期 | 可被多次订阅(冷流,默认) | 与单次 create() 调用绑定,不可复用 |
| 写入能力 | 不可写(只读流定义) | 可写(但仅允许 success/error 之一,且仅一次) |
| 典型用途 | 标准异步操作(DB 查询、HTTP 调用) | 集成回调式 SDK、手动编排复杂异步逻辑 |
| 类比 | CompletableFuture |
CompletableFuture.complete()(命令式履约) |
? 实践建议
- ✅ 优先使用工厂方法:如 Mono.just()、Mono.fromCallable()、Mono.fromFuture() —— 安全、简洁、符合响应式范式;
- ✅ 仅当必要时用 Mono.create() + MonoSink:例如对接无响应式支持的遗留异步 API、实现自定义超时/重试逻辑;
- ⚠️ 避免滥用 MonoSink:它打破链式声明式风格,增加状态管理复杂度,易引发并发或重复完成问题;
- ? 记住口诀:
Mono 是你 要什么(What),MonoSink 是你 怎么给(How)——且只给一次。
通过清晰区分二者职责,你既能写出声明式、可组合的响应式代码,也能在必要时精准介入底层信号控制,真正驾驭 Reactor 的强大能力。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










