如何在Spring Reactor中测试判断Publisher是否为已缓存的实例
检测Mono是否已缓存的可行方案
以下方案均不需要依赖内部类的直接引用:
方案1:类名字符串匹配
最简单的实现方式,直接比对运行时类的全限定名即可:
fun isCachedMono(publisher: Publisher<*>): Boolean { return publisher.javaClass.name == "reactor.core.publisher.MonoCacheTime" }
注意:该方案依赖Reactor的内部实现,版本迭代时缓存实现类名可能发生变更,升级版本时需要做兼容性校验
方案2:基于订阅行为判断
完全不依赖内部实现,利用缓存Mono的行为特征判断:未缓存的Mono每次订阅都会触发上游逻辑执行,缓存后的Mono只会触发一次上游执行:
import reactor.core.publisher.Mono import reactor.test.StepVerifier fun <T> checkIfCached(mono: Mono<T>): Boolean { var subscribeCount = 0 val countMono = mono.doOnSubscribe { subscribeCount++ } // 连续订阅两次 StepVerifier.create(countMono) .expectNextCount(1) .verifyComplete() StepVerifier.create(countMono) .expectNextCount(1) .verifyComplete() // 缓存过的Mono只会触发1次上游订阅 return subscribeCount == 1 }
注意:该方案需要实际触发订阅,有执行开销,适合单元测试场景,不推荐在生产环境做高频调用
方案3:基于Reactor官方Scannable接口判断
Reactor的所有内部Publisher都实现了Scannable接口,专门用于运行时探测组件属性,比直接匹配类名兼容性更好:
import reactor.core.Scannable fun isCachedMono(publisher: Publisher<*>): Boolean { val scannable = Scannable.from(publisher) // 可直接匹配类名,也可扫描缓存相关的属性实现更精准的判断 return scannable.javaClass.name == "reactor.core.publisher.MonoCacheTime" }
该方案是生产环境的优先选择,只要Reactor的Scannable规范不变就不会失效,还可以扩展读取缓存有效期、缓存命中率等属性
内容的提问来源于stack exchange,提问作者chrgue
相关产品推荐
相关产品推荐

