在使用@Cacheable
注解的时候遇到的这个问题
@Cacheable(value = RedisConstant.USER, key = "#id")
UserShow userShow(String id);
奇怪的是本地从没遇到过,生产上也是偶尔遇到,而@Cacheable
注解肯定支持key属性,查看日志也没找到原因,最终在网上的一篇文章里面看到和debug模式有关,反射无法获取到参数值。
进入日志打印的类里面看一下:
private Object generateKey(CacheOperationContext context, @Nullable Object result) {
Object key = context.generateKey(result);
if (key == null) {
throw new IllegalArgumentException("Null key returned for cache operation (maybe you are " +
"using named params on classes without debug info?) " + context.metadata.operation);
}
if (logger.isTraceEnabled()) {
logger.trace("Computed cache key '" + key + "' for operation " + context.metadata.operation);
}
return key;
}
好吧不管怎样,是由于context.generateKey(result);
取不到值造成的,然而本地可以debug就不会遇到这个问题,生产上无法debug就会遇到???
两种解决方式:
-
使用
#p0
在我理解中和MyBatis
中param0
类似?不使用反射查找出参数名,直接指定第一个参数,反正我一般不使用这个方法。 -
自定义
keyGenerator
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-annotations-cacheable
Redis配置类中注入bean@Bean(name = "idGenerator") public KeyGenerator idGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(params[0].toString()); return sb.toString(); } }; }
注意我这里使用的是
idGenerator
,而我在使用的时候接口参数中一般只有id字段,如果有其他的可以参考上面的链接自行配置。
接口注解重写:@Cacheable(value = RedisConstant.USER, keyGenerator = "idGenerator") UserShow userShow(String id);
问题解决,目前没再遇到过这个问题。