@Cacheable 注释在 Spring 中无法正常工作
@Cacheable annotation working not properly in Spring
我在 Spring 中使用 @Cacheable
注释时遇到了一个奇怪的行为。
我有一个方法标记为 @Cacheable
并且 returns 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..)
表达式returns,如预期,如果我第二次使用相同的参数调用此方法,缓存数据。
问题是 getNamesByDateAndCurrency
方法正在缓存执行 retainAll
方法后更改的数据。
我的问题是为什么外部操作 (retainAll
) 方法会影响缓存的响应?为什么它没有从 getNamesByDateAndCurrency
方法返回原始数据?
提前致谢!
Spring缓存通过引用将结果存储在缓存中。然后,使用的缓存框架(我认为在您的情况下为 Ehcache)将根据其配置存储结果。大多数框架默认会通过引用存储它,因为它要快得多。
您有 2 个解决方案:
- 以不可变的方式编写代码。所以在收到地图时,不要就地修改,只需创建一个副本即可。您可以通过将结果包装在
Collections.unmodifiableMap
中来确保它
- 告诉Ehcache 按值存储。这有点复杂,因为您需要能够 copy 该值。但它会透明地工作
请注意,无论您是将数据存储在堆上、磁盘上还是集群上,默认情况下它都会按预期工作。因为所有这些选项都需要复制键和值。只有堆上有 "by reference" 存储优化。
我在 Spring 中使用 @Cacheable
注释时遇到了一个奇怪的行为。
我有一个方法标记为 @Cacheable
并且 returns 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..)
表达式returns,如预期,如果我第二次使用相同的参数调用此方法,缓存数据。
问题是 getNamesByDateAndCurrency
方法正在缓存执行 retainAll
方法后更改的数据。
我的问题是为什么外部操作 (retainAll
) 方法会影响缓存的响应?为什么它没有从 getNamesByDateAndCurrency
方法返回原始数据?
提前致谢!
Spring缓存通过引用将结果存储在缓存中。然后,使用的缓存框架(我认为在您的情况下为 Ehcache)将根据其配置存储结果。大多数框架默认会通过引用存储它,因为它要快得多。
您有 2 个解决方案:
- 以不可变的方式编写代码。所以在收到地图时,不要就地修改,只需创建一个副本即可。您可以通过将结果包装在
Collections.unmodifiableMap
中来确保它
- 告诉Ehcache 按值存储。这有点复杂,因为您需要能够 copy 该值。但它会透明地工作
请注意,无论您是将数据存储在堆上、磁盘上还是集群上,默认情况下它都会按预期工作。因为所有这些选项都需要复制键和值。只有堆上有 "by reference" 存储优化。