背景
最近要在项目中使用一个简单的缓存,又不想动用流行的java缓存大杀器guava cache或者Caffeine,就想到了Spring自带的缓存,一个注解就搞定,多美啊。可惜Spring的注解缓存默认不支持设置缓存过期时间。在网上搜了半天,大都是基于RedisCacheManager实现的,有点繁琐,不够简洁。于是结合Spring的Scheduled和CacheEvict来实现自动过期的缓存,几行代码搞定,中小项目用用还是很香的。
好了上代码:
第一步 在Springboot启动类加相关注解
这个两个注解是必须的,否则缓存和定时器都不会起作用
@EnableScheduling //支持定期执行
@EnableCaching //支持缓存
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
第二步 使用@Cacheable、和@CacheEvict注解创建缓存类
@Cacheable、@CacheEvict注解的具体参数,请自行百度,太多例子,这里不再多说
@Component
public class MyCache {
//支持缓存的接口
@Cacheable(value="testcache01",key="#key")
public String getCache(String key) {
System.out.println("load:"+key);
//load data from db or remote interface
return "key:"+ LocalDateTime.now().toString();
}
//缓存过期方法,allEntries =true,代表该缓存名称的所有键都过期,可自行修改
@CacheEvict(value = "testcache01",allEntries = true)
public void expiredCache(String key) {
//啥都不用做,打个日志就行
System.out.println("expired:"+LocalDateTime.now().toString());
}
}
第三步、使用@Scheduled创建缓存过期任务
@Scheduled注解的参数很多,请自行调研,这里是固定没2秒执行一次,调用缓存类的过期方法
注意这个方法,不可以放在上面的缓存类中,因为AOP的问题,必须跨类执行,否则会不生效的
@Component
public class ExpireCache {
@Resource
MyCache myCache;
@Scheduled(fixedRate = 2*1000) //2秒过期
public void expiredCache() {
//调用缓存过期方法
myCache.expiredCache("test01");
}
}
到这里就一个简单的缓存就实现了。大家可能也发现了,这个简单的实现在高并发的情况下有缓存穿透的风险,大家可以在获取缓存的地方加个锁,比较easy。
后记
但是这个缓存应该没有实现lru,因此缓存的时间不能太长,不能太多。如果要在大型,高并发项目中,建议还是用guava cache,这个库对并发,过期时间控制的比较好。
我记得以前看过文章说Spring的cache也可以结合Caffeine来使用,需要实现一个基于Caffeine的CacheManager,具体实现请自行百度