Почему Spring @Cacheable не передает тип результата аннотированного метода его десериализатору? - PullRequest
0 голосов
/ 10 мая 2018

Это пример кода с Kotlin.

@ Конфигурация

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

1 Ответ

0 голосов
/ 19 сентября 2018

Ваш тип возврата может быть:

  • какой-то абстрактный класс
  • некоторый интерфейс

В этих случаях ваш тип возврата почти бесполезен для десериализации объекта. Кодирование фактического класса всегда работает.

...