Guava是什么?
Guava是一组Java的Google核心库,包括新的集合类型(例如multimap和multiset),不可变集合,图形库,函数类型,内存缓存以及用于并发,I / O,散列,基元的API /实用程序,反射,字符串处理等等!
Guava Cache呢?
当然是Guava的核心库之一,主要是用在数据的缓存。它有两种实现方式:CacheLoader与Callable
其他介绍我就不多说了,网上搜了一下,基本上都是此项目在GitHub上的翻译,github地址:https://github.com/google/guava/wiki/CachesExplained
1.引用
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
2.CacheLoader实现缓存
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.TimeUnit;
/**
* Created by XiChuan on 2018-12-11.
*/
public class TestGoogleCache {
//创建Cache
static LoadingCache<String, Object> cache =
CacheBuilder.newBuilder()
.refreshAfterWrite(4, TimeUnit.SECONDS) //设置缓存获取时长,如果key过期,就会在缓存中删除此value
.maximumSize(10) //最大缓存数量
.build(new CacheLoader<String, Object>() {
@Override
/** 当本地缓存没有此key的value值时,就会调用load方法进行查询,并添加到缓存中 **/
public Object load(String appKey) {
return queryFromDB(appKey);
}
});
/** 数据进行库进行查询**/
public static Object queryFromDB(String appKey){
System.out.println("query from db");
return System.currentTimeMillis();
}
public static void main(String[] args)throws Exception{
String key = "wechat";
for (int i=0; i<8; i++){
System.out.println("-----------i="+i+"------------------");
System.out.println("从cache获取的值为:"+cache.get(key));
Thread.sleep(1000); /**每获取一次睡眠1秒*/
}
}
}
日志:
-----------i=0------------------
query from db
从cache获取的值为:1544687107838
-----------i=1------------------
从cache获取的值为:1544687107838
-----------i=2------------------
从cache获取的值为:1544687107838
-----------i=3------------------
从cache获取的值为:1544687107838
-----------i=4------------------
从cache获取的值为:1544687107838
-----------i=5------------------
query from db
从cache获取的值为:1544687112842
-----------i=6------------------
从cache获取的值为:1544687112842
-----------i=7------------------
从cache获取的值为:1544687112842
Process finished with exit code 0
我们看日志可以看出,当第一次再cache中获取值的时候,key=wechat并没有value值,Cache会从数据库中查询。到第五秒的时候,key=wechat到期,Cache会删除value,并从数据库中重新获取。
3.Callable实现缓存
/**
* Created by XiChuan on 2018-12-11.
*/
public class TestGoogleCache {
//创建Cache
static Cache<String,Object> cache =
CacheBuilder.newBuilder()
.maximumSize(10) //设置最大缓存数量
.expireAfterWrite(4,TimeUnit.SECONDS) //设置缓存过期时间
.build();
/**从缓存中获取值*/
public static Object getValueFromCache(String appKey)throws Exception{
return cache.get(appKey, new Callable<Object>() {
/**当本地缓存没有此key的value值时,就会调用load方法进行查询,并添加到缓存中 */
@Override
public Object call() throws Exception {
return queryFromDB(appKey);
}
});
}
/** 数据进行库进行查询**/
public static Object queryFromDB(String appKey){
System.out.println("query from db");
return System.currentTimeMillis();
}
public static void main(String[] args)throws Exception{
String key = "wechat";
for (int i=0; i<8; i++){
System.out.println("-----------i="+i+"------------------");
System.out.println("从cache获取的值为:"+getValueFromCache(key));
Thread.sleep(1000); /**每获取一次睡眠1秒*/
}
}
}
日志:
-----------i=0------------------
query from db
从cache获取的值为:1544687715137
-----------i=1------------------
从cache获取的值为:1544687715137
-----------i=2------------------
从cache获取的值为:1544687715137
-----------i=3------------------
从cache获取的值为:1544687715137
-----------i=4------------------
query from db
从cache获取的值为:1544687719149
-----------i=5------------------
从cache获取的值为:1544687719149
-----------i=6------------------
从cache获取的值为:1544687719149
-----------i=7------------------
从cache获取的值为:1544687719149
Process finished with exit code 0
可以看出,处理的结果都是一样的。
4.其他有用的方法
有时候,我们并不想当缓存时间过期后才清除缓存项,我们可以显式地将缓存清除。
Cache.invalidate(key) //清除一个缓存
Cache.invalidateAll(keys) //根据keys批量清除
Cache.invalidateAll() //清除所有缓存
5.对Callable实现方式进行封装
@Configuration
public class CacheConfig {
public final static long CACHE_MAX_SIZE = 20; //最大缓存数量
public final static int CACHE_REFRESH = 10; //失效时长
@Bean(name = "access_token")
public Cache<String,Object> accessTokenCache(){
return CacheBuilder.newBuilder()
.maximumSize(CACHE_MAX_SIZE)
.expireAfterWrite(CACHE_REFRESH, TimeUnit.SECONDS)
.build();
}
public static Object getValue(Cache<String,Object> cache, String key, Callable<Object> callable)throws ExecutionException{
return cache.get(key,callable);
}
}
public interface WechatService {
Object getAccessToken()throws Exception;
}
/**
* Created by XiChuan on 2018-12-13.
*/
@Service
public class WechatServiceImpl implements WechatService {
@Autowired
@Qualifier(value = "access_token")
Cache<String,Object> accessTokenCache;
/** 从缓存中获取accessToken */
@Override
public Object getAccessToken() throws Exception{
return CacheConfig.getValue(accessTokenCache,"XICHUAN",() -> getFromApi());
}
/**模拟通过接口获取accessToken*/
private String getFromApi(){
System.out.println("-----从数据库中读取------------");
return "1234567890zxcvbnm";
}
}
此封装方式是在公司中看到大神封装的,看完后感觉挺实用的,然后就借鉴过来自己封装了一下。