spring5(springboot2)开始用Caffeine取代guava,至于其性能对比可以参考Caffeine给的测试结果各缓存性能对比。
这里贴出一个读写的对比
Caffeine在springboot中集成非常简单,可以通过配置文件来设置
spring:
cache:
cache-names: outLimit,notOutLimit
caffeine:
spec: initialCapacity=50,maximumSize=500,expireAfterWrite=5s,refreshAfterWrite=7s
type: caffeine
这种方法设置的简单,但是灵活性不够高,如上边设置的cache(cache name)所有的规则都是一样的。这块我没深入研究,不多做介绍。
左边这块是我在看Caffeine时做的一些配置。这些东西很多,我可能会分多篇文章来讲。
先来说下最常用的CacheManager
CacheManager的使用场景比较多,最常见的@Cacheable、@CachePut、@CacheEvict等默认都可以配合CacheManager使用。
先看下我集成的三个CacheManager
@Value("${caffeine.spec}")
private String caffeineSpec;
@Autowired
private CacheLoader cacheLoader;
@Bean
public CacheManager cacheManagerWithCacheLoading(){
logger.info("cacheManagerWithCacheLoading" );
Caffeine caffeine = Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(1000)
// .refreshAfterWrite(5,TimeUnit.SECONDS)
.expireAfterWrite(50,TimeUnit.SECONDS);
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setAllowNullValues(true);
cacheManager.setCaffeine(caffeine);
// cacheManager.setCacheLoader(cacheLoader);
cacheManager.setCacheNames(getNames());
return cacheManager;
}
@Bean(name = "caffeine")
@Primary
public CacheManager cacheManagerWithCaffeine(){
logger.info("This is cacheManagerWithCaffeine");
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
Caffeine caffeine = Caffeine.newBuilder()
//cache的初始容量值
.initialCapacity(100)
//maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight不可以同时使用,
.maximumSize(1000);
//控制最大权重
// .maximumWeight(100);
// .expireAfter();
//使用refreshAfterWrite必须要设置cacheLoader
// .refreshAfterWrite(5,TimeUnit.SECONDS);
cacheManager.setCaffeine(caffeine);
// cacheManager.setCacheLoader(cacheLoader);
cacheManager.setCacheNames(getNames());
// cacheManager.setAllowNullValues(false);
return cacheManager;
}
@Bean(name = "caffeineSpec")
public CacheManager cacheManagerWithCaffeineFromSpec(){
CaffeineSpec spec = CaffeineSpec.parse(caffeineSpec);
Caffeine caffeine = Caffeine.from(spec);
//此方法等同于上面from(spec)
// Caffeine caffeine = Caffeine.from(caffeineSpec);
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(caffeine);
cacheManager.setCacheNames(getNames());
return cacheManager;
}
private static List getNames(){
List names = new ArrayList<>(2);
names.add("outLimit");
names.add("notOutLimit");
return names;
}
CacheLoader会在后面介绍,它是cache的一种加载策略,key不存在或者key过期之类的都可以通过CacheLoader来获得/重新获得数据。
cacheManagerWithCaffeine这个bean是以Caffeine为基础来设置一个CacheManager。如果设置refreshAfterWrite的话后边必须要设置cacheLoader。如果不设置的话,项目启动的时候会抛异常。
这里有个setCacheNames,主要是用来创建多个cache的,但是多个cache使用相同的策略。
cacheManagerWithCacheLoading这个bean是创建了一个带有CacheLoader的bean。它跟cacheManagerWithCaffeine这块的主要区别是,最初我在cacheManagerWithCaffeine里只是想创建一个简单的key-value存储,没有CacheLoader模块,所以cacheManagerWithCaffeine这个bean如果里边的key过期或不存在cache中是获取不到数据的,直接返回null。但是cacheManagerWithCacheLoading不同,如果key过期或不存在会从他的CacheLoader策略里重新加载数据。
cacheManagerWithCaffeineFromSpec是通过spec来创建cacheManager。
先看下面两行代码
CaffeineSpec spec = CaffeineSpec.parse(caffeineSpec);
Caffeine caffeine = Caffeine.from(spec);
caffeineSpec这里是从配置文件中获取的配置,如配置文件设置如下
caffeine:
spec: initialCapacity=50,maximumSize=500,expireAfterWrite=5s
caffeineSpec是个符合其规则的字符串。
进入其源码
@SuppressWarnings("StringSplitter")
public static CaffeineSpec parse(String specification) {
CaffeineSpec spec = new CaffeineSpec(specification);
for (String option : specification.split(SPLIT_OPTIONS)) {
spec.parseOption(option.trim());
}
return spec;
}
可以看到其处理方式,非常简单。
Caffeine caffeine = Caffeine.from(spec);这行就是加载spec中的信息,自己点击下就知道什么意思了。
代码中写了很多注释,这里不多做解释了,如果有不明白的可以留言,或者在后边我会介绍其它块的时候点出。
代码的github地址Caffeine。这只是我自己摸索的时候写的,有些不太规范,仅供大家参考。