kotlin - 如何将 @Cacheable 与 Kotlin 挂起功能一起使用
问题描述
我在 Kotlin 和 Spring Boot 项目中工作,我正在尝试使用 Caffeine 进行缓存。我有一个带有暂停功能的服务,可以进行 http 调用。这是我的配置:
@Bean
open fun caffeineConfig(): @NonNull Caffeine<Any, Any> {
return Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.SECONDS)
}
@Bean
open fun cacheManager(caffeine: Caffeine<Any, Any>): CacheManager {
val caffeineCacheManager = CaffeineCacheManager()
caffeineCacheManager.getCache("test")
caffeineCacheManager.setCaffeine(caffeine)
return caffeineCacheManager
}
这是我要缓存的功能:
@Cacheable(value = ["test"])
open suspend fun getString(id: String): String {
return client.getString(id)
}
但似乎缓存不起作用,因为我可以从日志中看到每次调用服务函数时都会调用客户端。@Cacheable
不适用于暂停功能?还是我错过了其他东西?
解决方案
的文档@Cacheable
说:
每次调用建议的方法时,都会应用缓存行为,检查是否已经为给定的参数调用了该方法。合理的默认值仅使用方法参数来计算密钥,但可以通过 key() 属性提供 SpEL 表达式,或者自定义 KeyGenerator 实现可以替换默认值(参见 keyGenerator())。
suspend
修饰符在生成的代码中插入一个参数,该Continuation<String>
参数接受来自调用者的输入。这大概意味着每个调用都有自己的延续,并且缓存将其检测为唯一调用。
但是,由于返回值也会根据延续而改变,因此您不能让缓存忽略延续参数。更好的方法是不使用suspend
函数,而是返回Deferred
消费者可以共享的 a:
@Cacheable(value = ["test"])
open fun getString(id: String): Deferred<String> {
return someScope.async {
client.getString(id)
}
}
// Consumer side
getString(id).await()
这应该适用于标准缓存机制,因为Deferred
它是一个普通对象,不需要特殊参数。
推荐阅读
- php - 未针对指定类别 ID 显示自定义帖子类型帖子
- python - python中的FTDI串行转换器问题
- vue.js - v-for 内的 v-for 无限循环
- r - 如何使用 R 生成序列 (1,2,3...n,2,3...n,3,4..n...n-1,n)
- prometheus - 如何使用 Prometheus 来提醒特定的错误信息?
- react-native - 使用 react native sectionList 获取数据
- excel - 使用 Excel VBA 根据单元格的值求平均值?
- xcode - Xcode 10 GM 不显示故事板图形元素
- vuejs2 - VueJS - 使用动态数据更新 URL
- jquery - html表单jquery验证