【问题标题】:Why does Spring @Cacheable not pass the annotated method's result type to its deserializer?为什么 Spring @Cacheable 不将带注释的方法的结果类型传递给它的反序列化器?
【发布时间】:2018-05-10 01:46:30
【问题描述】:

这是 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 as property”添加到 Redis 缓存条目。

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

  1. 内存更少
  2. 易于串行器,即objectMapper.readValue(str, T)

用于说明的带注释的 Spring 代码

// 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);
}

【问题讨论】:

    标签: spring jackson spring-data-redis spring-cache


    【解决方案1】:

    您的返回类型可能是:

    • 一些抽象类
    • 一些界面

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

    【讨论】:

      猜你喜欢
      • 2016-07-22
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      相关资源
      最近更新 更多