如何在 Kotlin 挂起函数中使用 @Cacheable
How to use @Cacheable with Kotlin suspend funcion
我在 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
的文档说:
Each time an advised method is invoked, caching behavior will be applied, checking whether the method has been already invoked for the given arguments. A sensible default simply uses the method parameters to compute the key, but a SpEL expression can be provided via the key() attribute, or a custom KeyGenerator implementation can replace the default one (see keyGenerator()).
suspend
修饰符在生成的代码中插入一个 Continuation<String>
参数,该参数接受来自调用者的输入。这大概意味着每次调用都有自己的延续,并且缓存将其检测为唯一调用。
然而,由于 return 值也会根据延续而改变,因此您不能让缓存忽略延续参数。更好的方法是不使用 suspend
函数,而是 returning 消费者可以共享的 Deferred
:
@Cacheable(value = ["test"])
open fun getString(id: String): Deferred<String> {
return someScope.async {
client.getString(id)
}
}
// Consumer side
getString(id).await()
这应该适用于标准缓存机制,因为 Deferred
是一个普通对象,不需要特殊参数。
我在 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
的文档说:
Each time an advised method is invoked, caching behavior will be applied, checking whether the method has been already invoked for the given arguments. A sensible default simply uses the method parameters to compute the key, but a SpEL expression can be provided via the key() attribute, or a custom KeyGenerator implementation can replace the default one (see keyGenerator()).
suspend
修饰符在生成的代码中插入一个 Continuation<String>
参数,该参数接受来自调用者的输入。这大概意味着每次调用都有自己的延续,并且缓存将其检测为唯一调用。
然而,由于 return 值也会根据延续而改变,因此您不能让缓存忽略延续参数。更好的方法是不使用 suspend
函数,而是 returning 消费者可以共享的 Deferred
:
@Cacheable(value = ["test"])
open fun getString(id: String): Deferred<String> {
return someScope.async {
client.getString(id)
}
}
// Consumer side
getString(id).await()
这应该适用于标准缓存机制,因为 Deferred
是一个普通对象,不需要特殊参数。