我的 Spring webflux flatMap、doOnNext、doFinally 没有被内部 Mono 调用?
My Spring webflux flatMap, doOnNext, doFinally is not getting called for inner Mono?
我对 reactor 完全陌生。
我的 flatMap、doOnNext、doFinally 没有被内部 Mono 调用。
我添加了描述问题的样本测试和输出。即使我将 getMeIntegerMono2
与 getMeStringMono
互换,它也不会被调用,
我做错了什么吗?
@Test
public void prodBug() {
System.out.println(Final());
}
String Final(){
final String[] val = new String[1];
System.out.println("1 - "+Thread.currentThread().getName());
Mono<Integer> intMono =
getMeIntegerMono("2")
.doOnNext(integer -> {
getMeIntegerMono2("21")
.flatMap(s -> getMeStringMono(String.valueOf(s)));
});
System.out.println("2 - "+Thread.currentThread().getName());
intMono.subscribe(integer -> {
val[0] =String.valueOf(integer);
});
System.out.println("3 - "+Thread.currentThread().getName());
return val[0];
}
Mono<String> getMeStringMono(String val){
System.out.println("String Mono - "+Thread.currentThread().getName());
return Mono.just(val);
}
Mono<Integer> getMeIntegerMono(String val){
System.out.println("Integer Mono - "+Thread.currentThread().getName());
return Mono.just(Integer.parseInt(val));
}
Mono<Integer> getMeIntegerMono2(String val){
System.out.println("Integer Mono2 - "+Thread.currentThread().getName());
return Mono.just(Integer.parseInt(val));
}
输出是
1 - main
Integer Mono - main
2 - main
Integer Mono2 - main
3 - main
2
进程已完成,退出代码为 0
您的代码存在一些问题。
在 Reactor 中,nothing happens until you subscribe。也就是说,仅仅创建一个 Mono 不会 做 任何事情。在传递给 doOnNext
的函数中,您创建了一个从未被订阅的 Mono。因此,您传递给 flatMap
的函数将永远不会被调用。尝试使用 flatMap
而不是 doOnNext
(您需要 fiddle 稍微调整一下类型才能使其正常工作)。
您测试此方法的一个问题来自 "assembly time" 和 "execution time." 之间的 difference 在您所有的 getMe*
方法中,您立即打印一些东西并然后 return 一个单声道。这实际上在调试时具有误导性,因为打印将在汇编期间发生,即使从未执行 returned Mono。您可以在执行时执行副作用,而不是使用 Mono.defer()
或 Mono.fromSupplier()
.
使用数组来绕过 Java 对变量和 lambda 的限制的技术是不好的做法,虽然它在这种情况下可能有效,但您应该改掉这种习惯,因为它非常脆弱。要理解原因,请想象您的链中的某个 Mono 在另一个线程中执行昂贵的操作。这意味着您传递给 subscribe
的函数将在 在 Final()
已经 return 之后被调用。
我对 reactor 完全陌生。
我的 flatMap、doOnNext、doFinally 没有被内部 Mono 调用。
我添加了描述问题的样本测试和输出。即使我将 getMeIntegerMono2
与 getMeStringMono
互换,它也不会被调用,
我做错了什么吗?
@Test
public void prodBug() {
System.out.println(Final());
}
String Final(){
final String[] val = new String[1];
System.out.println("1 - "+Thread.currentThread().getName());
Mono<Integer> intMono =
getMeIntegerMono("2")
.doOnNext(integer -> {
getMeIntegerMono2("21")
.flatMap(s -> getMeStringMono(String.valueOf(s)));
});
System.out.println("2 - "+Thread.currentThread().getName());
intMono.subscribe(integer -> {
val[0] =String.valueOf(integer);
});
System.out.println("3 - "+Thread.currentThread().getName());
return val[0];
}
Mono<String> getMeStringMono(String val){
System.out.println("String Mono - "+Thread.currentThread().getName());
return Mono.just(val);
}
Mono<Integer> getMeIntegerMono(String val){
System.out.println("Integer Mono - "+Thread.currentThread().getName());
return Mono.just(Integer.parseInt(val));
}
Mono<Integer> getMeIntegerMono2(String val){
System.out.println("Integer Mono2 - "+Thread.currentThread().getName());
return Mono.just(Integer.parseInt(val));
}
输出是
1 - main
Integer Mono - main
2 - main
Integer Mono2 - main
3 - main
2
进程已完成,退出代码为 0
您的代码存在一些问题。
在 Reactor 中,nothing happens until you subscribe。也就是说,仅仅创建一个 Mono 不会 做 任何事情。在传递给 doOnNext
的函数中,您创建了一个从未被订阅的 Mono。因此,您传递给 flatMap
的函数将永远不会被调用。尝试使用 flatMap
而不是 doOnNext
(您需要 fiddle 稍微调整一下类型才能使其正常工作)。
您测试此方法的一个问题来自 "assembly time" 和 "execution time." 之间的 difference 在您所有的 getMe*
方法中,您立即打印一些东西并然后 return 一个单声道。这实际上在调试时具有误导性,因为打印将在汇编期间发生,即使从未执行 returned Mono。您可以在执行时执行副作用,而不是使用 Mono.defer()
或 Mono.fromSupplier()
.
使用数组来绕过 Java 对变量和 lambda 的限制的技术是不好的做法,虽然它在这种情况下可能有效,但您应该改掉这种习惯,因为它非常脆弱。要理解原因,请想象您的链中的某个 Mono 在另一个线程中执行昂贵的操作。这意味着您传递给 subscribe
的函数将在 在 Final()
已经 return 之后被调用。