@Cacheable注释在Spring中工作不正常

时间:2018-02-05 11:42:44

标签: java spring ehcache

我在Spring中使用@Cacheable注释时遇到了一个奇怪的行为。 我有一个标记为@Cacheable的方法,它返回Map:

//dao layer
@Cacheable(value = "Cache1")
public Map<String, String> getNamesByDateAndCurrency(LocalDate date, String currency) {
    // Returns some map
}

我从以下方法调用此方法,并使用retainAll()方法更改地图:

//service layer
@Autowired
private DaoImpl dao;
...
@Cacheable( value = "Cache2")
public List<Integer> getUUIDs(Integer requestNumber, Set<String> set) {
   //some code..
   Map<String, String> names = dao.getNamesByDateAndCurrency(params..);
   names.keySet().retainAll(set);
   //some other code, no any changes of map in further
}
如果我使用相同的参数第二次调用此方法,

dao.getNamesByDateAndCurrency(params..)表达式会按预期返回缓存的数据。

问题是getNamesByDateAndCurrency方法在执行retainAll方法后缓存了更改的数据。

我的问题是为什么外部操作(retainAll)方法会影响缓存的响应?为什么它没有从getNamesByDateAndCurrency方法返回原始数据?

提前致谢!

1 个答案:

答案 0 :(得分:1)

Spring缓存通过引用将结果存储在缓存中。然后,使用的缓存框架(我认为是Ehcache)将根据其配置存储结果。大多数框架默认会通过引用存储它,因为它更快。

你有2个解决方案:

  1. 代码以不可变的方式。因此,在接收地图时,只需创建一个副本,而不是在适当的位置进行修改。您可以通过将结果包装在Collections.unmodifiableMap
  2. 中来确保它
  3. 告诉Ehcache按值存储。这涉及更多,因为您需要能够copy该值。但它会透明地工作
  4. 请注意,无论是在堆上,磁盘上还是群集上存储数据,默认情况下它都会按预期工作。因为所有这些选项都需要复制键和值。只有on-heap具有“按引用”存储优化。