为什么 Spring @Cacheable没有将带注释的方法的结果类型传递给它的反序列化器?



这是使用 Kotlin 的示例代码。

@Configuration

@Bean("cacheManager1hour")
fun cacheManager1hour(@Qualifier("cacheConfig") cacheConfiguration: RedisCacheConfiguration, redisConnectionFactory: RedisConnectionFactory): CacheManager {
cacheConfiguration.entryTtl(Duration.ofSeconds(60 * 60))
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfiguration)
.build()
}
@Bean("cacheConfig")
fun cacheConfig(objectMapper:ObjectMapper): RedisCacheConfiguration {
return RedisCacheConfiguration.defaultCacheConfig()
.computePrefixWith { cacheName -> "yaya:$cacheName:" }
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(GenericJackson2JsonRedisSerializer()))
}

@RestController

@Cacheable(value = "book", key = "#root.methodName", cacheManager = "cacheManager1hour")
fun getBook(): Book {
return Book()
}
class Book  {
var asdasd:String? = "TEST"
var expires_in = 123
}

GenericJackson2JsonRedisSerializer无法处理"kotlin 类",我们需要将"@class 作为属性"添加到 Redis 缓存条目中。

无论如何,为什么我们需要@class?Spring 上下文知道结果的类型,为什么它没有被传递?我们将有两个好处:

  1. 更少的内存
  2. 易于序列化程序,即objectMapper.readValue(str, T)

带注释的弹簧代码用于说明

// org.springframework.cache.interceptor.CacheAspectSupport
@Nullable
private Cache.ValueWrapper findInCaches(CacheOperationContext context, Object key) {
for (Cache cache : context.getCaches()) {
// --> maybe we can pass the context.method.returnType to doGet
Cache.ValueWrapper wrapper = doGet(cache, key); 
if (wrapper != null) {
if (logger.isTraceEnabled()) {
logger.trace("Cache entry for key '" + key + "' found in cache '" + 
cache.getName() + "'");
}
return wrapper;
}
}
return null;
}
// org.springframework.data.redis.cache.RedisCache
@Override
protected Object lookup(Object key) { 
// -> there will get the deserialized type can pass to Jackson
byte[] value = cacheWriter.get(name, createAndConvertCacheKey(key));
if (value == null) {
return null;
}
return deserializeCacheValue(value);
}

返回类型可以是:

  • 一些抽象类
  • 一些界面

在这些情况下,返回类型对于反序列化对象几乎毫无用处。对实际类进行编码始终有效。

最新更新