我正在玩Project Reactor和反应式MongoDB存储库。我有以下代码:
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document
public class Person {
@Id
Integer id;
String name;
}
public interface ReactivePersonRepository extends ReactiveCrudRepository<Person, Integer> {
}
和主要的@SpringBootApplication
类:
@SpringBootApplication
@EnableReactiveMongoRepositories
@RequiredArgsConstructor
public class ReactiveDatabaseApplication {
private final ReactivePersonRepository reactivePersonRepository;
public static void main(String[] args) {
SpringApplication.run(ReactiveDatabaseApplication.class, args);
}
@PostConstruct
public void postConstruct() {
Scheduler single = Schedulers.newSingle("single-scheduler");
IntStream.range(0, 10).forEach(i ->
Flux.just(Person.builder()
.id(i)
.name("PersonName")
.build())
.flatMap(personToSave -> {
System.out.println(String.format(
"Saving person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.save(personToSave);
})
//.publishOn(single)
.flatMap(savedPerson -> {
System.out.println(String.format(
"Finding person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.findById(savedPerson.getId());
})
//.publishOn(single)
.flatMap(foundPerson -> {
System.out.println(String.format(
"Deleting person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.deleteById(foundPerson.getId());
})
//.publishOn(single)
.subscribeOn(single)
.subscribe(aVoid -> System.out.println(String.format(
"Subscription from thread %s", Thread.currentThread().getName()))));
}
}
Flux::subscribeOn
方法说明说:
因此,将此运算符放置在链中的任何位置也会影响 来自的onNext / onError / onComplete信号的执行*上下文 链的起点,直到*下一次出现{@link publishOn(Scheduler)publishOn}
这让我有些困惑,因为当我在处理链中没有指定任何publishOn
时,线程名称的打印值是:
从线程单调度程序1中拯救人员-符合预期
从线程-13查找人
从线程Thread-6查找人
从线程-15查找人
从线程Thread-6中删除人
从线程Thread-5中删除人员
从线程Thread-4中删除人员
我不明白为什么。 subscribeOn
方法中指定的调度程序是否应该用于每次flatMap
执行?
当我取消注释publishOn
行时,一切都由给定的单个调度程序执行,这与预期的一样。
谁能解释为什么没有flatMap
时publishOn
操作不使用单个调度程序?
答案 0 :(得分:1)
这个人为的例子可能更清楚:
Scheduler single = Schedulers.newSingle("single-scheduler");
Flux.just("Bob")
.flatMap(x -> {
System.out.println(String.format(
"Saving person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.flatMap(x -> {
System.out.println(String.format(
"Finding person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.flatMap(x -> {
System.out.println(String.format(
"Deleting person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.subscribeOn(single)
.subscribe(aVoid -> System.out.println(String.format(
"Subscription from thread %s", Thread.currentThread().getName())));
哪个会给出类似的内容:
Saving person from thread single-scheduler-1
Finding person from thread elastic-2
Deleting person from thread elastic-3
Subscription from thread elastic-4
或者,换句话说,您的反应式存储库不在同一调度程序上发布,并且这是您看到行为的原因。 “直到下一次出现publishOn()
时,这并不意味着下次您的代码调用publishOn()
,它也可以位于您的{ {1}}个电话,您将无法控制。