如何泛化Reactor框架中的logBefore函数?
泛化Reactor日志函数的问题解决
问题原因
你泛化后的logBefore方法,编译器无法从r -> log.info(...)这个lambda表达式中推断出泛型参数T的具体类型,默认将其推断为Object,导致返回的Flux<Object>与后续switchIfEmpty中client.retrieveData(request)返回的Flux<ServerSentEvent<MyObject>>类型不兼容,从而触发编译报错。
解决方案
方案一:调用时显式指定泛型类型
在调用logBefore时,明确指定泛型参数T的具体类型,帮助编译器完成类型推断:
public Flux<ServerSentEvent<MyObject>> myMethod(@Valid @RequestBody MyRequest request) { return logBefore<ServerSentEvent<MyObject>>(r -> log.info("[Enter] myMethod() called.")) .switchIfEmpty(client.retrieveData(request)); }
方案二:优化方法实现,适配Reactor操作符风格
原实现通过empty()+switchIfEmpty的方式绕了一圈,其实可以直接利用Reactor的doFirst操作符,让日志逻辑更自然,同时自动完成泛型推断:
// 泛化后的日志方法 public static <T> Flux<T> logBefore(Flux<T> targetFlux, Runnable logAction) { return targetFlux.doFirst(logAction); } // 调用方式 public Flux<ServerSentEvent<MyObject>> myMethod(@Valid @RequestBody MyRequest request) { return logBefore(client.retrieveData(request), () -> log.info("[Enter] myMethod() called.")); }
doFirst会在Flux被订阅时立即执行日志逻辑,完全符合你“调用另一个Flux前记录信息”的需求,同时避免了类型推断问题,代码更简洁直观。
方案三:通过辅助变量明确消费者类型
如果不想修改原方法的结构,可以先定义一个类型明确的Consumer变量,再传入logBefore:
public Flux<ServerSentEvent<MyObject>> myMethod(@Valid @RequestBody MyRequest request) { Consumer<ServerSentEvent<MyObject>> logConsumer = r -> log.info("[Enter] myMethod() called."); return logBefore(logConsumer) .switchIfEmpty(client.retrieveData(request)); }
内容的提问来源于stack exchange,提问作者René Winkler
相关产品推荐
相关产品推荐

