欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Spring-Cache key配置注意事项介绍

程序员文章站 2024-04-01 21:49:04
为了提升项目的并发性能,考虑引入本地内存cache,对:外部数据源访问、restful api调用、可重用的复杂计算 等3种类型的函数处理结果进行缓存。目前采用的是spri...

为了提升项目的并发性能,考虑引入本地内存cache,对:外部数据源访问、restful api调用、可重用的复杂计算 等3种类型的函数处理结果进行缓存。目前采用的是spring cache的@cacheable注解方式,缓存具体实现选取的是guava cache。
具体缓存的配置此处不再介绍,重点对于key的配置进行说明:

1、基本形式

@cacheable(value="cachename", key"#id")  
public resultdto method(int id);  

2、组合形式

@cacheable(value="cachename", key"t(string).valueof(#name).concat('-').concat(#password))  
public resultdto method(int name, string password);  

3、对象形式

@cacheable(value="cachename", key"#user.id) 
public resultdto method(user user); 

4、自定义key生成器

@cacheable(value="gomeo2ocache", keygenerator = "keygenerator") 
public resultdto method(user user); 

注意:spring默认的simplekeygenerator是不会将函数名组合进key中的

如下:

@component 
public class cachetestimpl implements cachetest { 
  @cacheable("databasecache") 
  public long test1() 
  { return 1l; } 
  @cacheable("databasecache") 
  public long test2() 
  { return 2l; } 
  @cacheable("databasecache") 
  public long test3() 
  { return 3l; } 
  @cacheable("databasecache") 
  public string test4() 
  { return "4"; } 
} 

我们期望输出:

1 
2 
3 
4

实际却输出:

1 
1 
1 
classcastexception: java.lang.long cannot be cast to java.lang.string 

此外,原子类型的数组,直接作为key使用也是不会生效的

为了解决上述2个问题,自定义了一个keygenerator如下:

class cachekeygenerator implements keygenerator { 
  // custom cache key 
  public static final int no_param_key = 0; 
  public static final int null_param_key = 53; 
  @override 
  public object generate(object target, method method, object... params) { 
    stringbuilder key = new stringbuilder(); 
    key.append(target.getclass().getsimplename()).append(".").append(method.getname()).append(":"); 
    if (params.length == 0) { 
      return key.append(no_param_key).tostring(); 
    } 
    for (object param : params) { 
      if (param == null) { 
        log.warn("input null param for spring cache, use default key={}", null_param_key); 
        key.append(null_param_key); 
      } else if (classutils.isprimitivearray(param.getclass())) { 
        int length = array.getlength(param); 
        for (int i = 0; i < length; i++) { 
          key.append(array.get(param, i)); 
          key.append(','); 
        } 
      } else if (classutils.isprimitiveorwrapper(param.getclass()) || param instanceof string) { 
        key.append(param); 
      } else { 
        log.warn("using an object as a cache key may lead to unexpected results. " + 
            "either use @cacheable(key=..) or implement cachekey. method is " + target.getclass() + "#" + method.getname()); 
        key.append(param.hashcode()); 
      } 
      key.append('-'); 
    } 
    string finalkey = key.tostring(); 
    long cachekeyhash = hashing.murmur3_128().hashstring(finalkey, charset.defaultcharset()).aslong(); 
    log.debug("using cache key={} hashcode={}", finalkey, cachekeyhash); 
    return key.tostring(); 
  } 
} 

采用此方式后可以解决:多参数、原子类型数组、方法名识别 等问题

总结

以上就是本文关于java spring-cache key配置注意事项介绍的全部内容,感兴趣的朋友可以继续参阅:spark之standalone模式部署配置详解、、java之spring注解配置bean实例代码解析等,如有不足之处,欢迎留言指出,小编会及时回复大家并修正,给广大编程爱好者提供更好的阅读体验,希望对大家有所帮助。在此也非常希望朋友们对本站多多支持!