我正在使用 Spring 4.0.3,并利用 EhCache 2.8.1 支持的缓存抽象功能。
我担心方法级别的注释在编辑@Cacheable
时@CacheEvict
可能无法正确锁定缓存,从而导致线程安全问题。我下面的测试似乎证实了这一点。我的问题是,我是在滥用框架还是误解了我的测试结果?或者我得出的结论是正确的,注释不会导致缓存被正确锁定,因此使用@CacheEvict
不能保证未来的读取将是有效的?
测试:
创建一个数据库表来存储一个计数器值
create table counter
(
counter integer
);
insert into counter values(0);
在 ehcache.xml 中创建一个条目来缓存计数器值
<cache name="counter"
eternal="true"
maxElementsInMemory="1"/>
在 Spring 控制器中创建两种请求映射方法——一种是读取计数器的值并在长时间延迟后返回,另一种是递增值然后快速返回
@RequestMapping("/viewcounter")
@ResponseBody
@Cacheable(value = "counter", key = "1")
public int readCounter() {
int count = dao.selectInteger("select counter from counter");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return count;
}
@RequestMapping("/incrementcounter")
@ResponseBody
@CacheEvict(value = "counter", key = "1")
public int incrementCounter() {
dao.update("update counter set counter = counter + 1");
int count = dao.selectInteger("select counter from counter");
return count;
}
在两种不同的场景下遵循这三个步骤——首先从控制器方法中删除缓存注释,然后将它们添加回
- 访问
/incrementcounter
- 在一个浏览器选项卡中,访问
/viewcounter
,然后在发起此请求后立即/incrementcounter
在另一个选项卡 中访问 - 访问
/viewcounter
试验结果
Expected result: 2
Actual result without caching: 2
Actual result with caching: 1
缓存结果是错误的,是吗?