当前位置: 首页 > 面试题库 >

使用Spring KeyGenerator无法生成唯一的缓存密钥

端木鹏
2023-03-14
问题内容

我在使用@Cacheable注释的缓存键在Spring中发生冲突时遇到问题。例如,使用以下两种方法:

@Cacheable("doOneThing")
public void doOneThing(String name) {
  // do something with name
}

@Cacheable("doAnotherThing")
public void doAnotherThing(String name) {
  // do some other thing with name
}

这是我的缓存配置,其中添加了一个keyGenerator和一个cacheManagerbean:

@Configuration
@EnableCaching
public class CacheConfig {

  @Bean
  public JedisConnectionFactory redisConnectionFactory() {
    return new JedisConnectionFactory();
  }

  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
    RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
    redisTemplate.setConnectionFactory(cf);
    return redisTemplate;
  }

  @Bean
  public CacheManager cacheManager(RedisTemplate redisTemplate) {
    return new RedisCacheManager(redisTemplate);
  }

  @Bean
  public KeyGenerator keyGenerator() {
    return new KeyGenerator() {
      @Override
      public Object generate(Object o, Method method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append(o.getClass().getName());
        sb.append(method.getName());
        for (Object param : params) {
          sb.append(param.toString());
        }
        return sb.toString();
      }
    };
  }
}

由于某种原因,缓存键始终设置为name方法中的参数,而不是方法的结果keyGenerator.generate(..),从而导致两个方法返回相同的缓存结果。

我知道我可以在每个@Cacheable注释上手动指定键,但是对于我想要缓存的每种方法来说,这似乎有点扩展。

编辑

我注意到,将注释keyGenerator内的选项设置@Cacheable为我的bean的名称可以解决此问题,如下所示:

@Cacheable(value = "doOneThing", keyGenerator = "keyGenerator")
public void doOneThing(String name) {
  // do something with name
}

并在类keyGenerator@CacheConfig注释中设置选项也可以解决该问题。似乎这不是必需的。我想念什么吗?


问题答案:

您的配置应实现CachingConfigurer(通常从扩展CachingConfigurerSupport),以自定义缓存的工作方式。



 类似资料:
  • 我已经使用openssl生成了一个私钥,并在Terminal/command中执行以下命令: null 所有这些都无法解密我的密钥。下面是我根据这篇文章编写的类[https://stackoverflow.com/questions/35276820/decrypting-an-openssl-pem-encoded-rsa-privest-key-with-java]: 我对安全问题一无所知,所

  • 问题 你想随机生成一个唯一的标识符。 解决方案 可以根据一个随机数值生成一个 Base 36 编码的字符串。 uniqueId = (length=8) -> id = "" id += Math.random().toString(36).substr(2) while id.length < length id.substr 0, length uniqueId() # =

  • 问题内容: 如何使用数据库查询回调设置变量值?我该怎么办? 问题答案: 自从使用node.js已经有一段时间了,但是我想我可以提供帮助。 首先,在node中,您只有一个线程,应该使用回调。您的代码将发生的情况是查询将排队等待执行,但是循环将毫无意义地连续作为繁忙循环运行。 您应该可以通过以下回调来解决您的问题: 并这样使用 我在大约2年内没有编写任何node / js的代码,也没有进行测试,但是基

  • 我有下面的项目结构 我在中有一个目录名为。 我的Dockerfile如下: 在我运行下面的命令从这个docker文件构建图像之后 我得到了下面的错误 我的问题是为什么我有这个错误?以及如何解决它? 我在Windows 10 20H2 19042.964上使用了 我看到Docker-未能计算缓存密钥:未找到-在Visual Studio和一些内部链接中运行良好,但没有找到任何有用的东西。 我正在处理

  • 问题内容: 我需要为数据库主键列生成唯一的Long ID。 我以为我可以使用 UUID.randomUUID()。getMostSignificantBits(), 但是有时它会产生一些负数,这对我来说也是个问题。 是否有可能仅从UUID生成正数长?会有数十亿个条目,因此我希望每个生成的键必须唯一。 问题答案: 之所以起作用,是因为当您按位与1进行操作时,它允许按原样传递同一位数字;当您按位与0进