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

时间:2018-05-10 01:46:30

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

这是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)
  3. 带注释的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);
    }
    

1 个答案:

答案 0 :(得分:0)

您的退货类型可能是:

  • 一些抽象类
  • 某些界面

在这种情况下,您的返回类型对反序列化对象几乎没有用。编码实际的类始终有效。