Guava------------Cache使用方法
简单从这几个方面描述一下如何使用Cache,对Cache的各种原理介绍此处不涉及.
1.使用场景
2.如何使用Cache
3.创建方式
4. 如何和Spring搭配使用
+------------------------------------------------------分割线-------------------------------------------------------+
1. Cache的使用场景
一般而言,对于那些频繁需要查询比对的热点数据,我们采用使用缓存,对于数据量较小的,几条,几十条数据,而且需要加缓存的接口较少,这时候我们会采用Cache,建议使用Google提供的guava Cache,它简单易用的同时,性能也好. 而且线程安全(原因看源码) .对于那些较大数据量的,或者需要加缓存的接口较多的项目,可以去考虑Redis,memcached等等
2. 如何使用Cache
和Map的使用方式差不多,也可以和Spring结合,使用@Cacheable注解使用.
3. 创建方式
1. Cache Callable
2. LoadingCache
方式一:
package info.sanaulla.cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.junit.Test; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-17 16:59
* Version: default 1.0.0
* Class description:
* <p/>
* *********************************************************
*/
public class CacheDemo {
private static Cache<Object, Object> cache = CacheBuilder.newBuilder()
.maximumSize(100).expireAfterWrite(24, TimeUnit.HOURS)
.recordStats()
.build(); public static Object get(Object key) throws ExecutionException { Object var = cache.get(key, new Callable<Object>() {
@Override
public Object call() throws Exception {
System.out.println("如果没有值,就执行其他方式去获取值");
String var = "Google.com.sg";
return var;
}
});
return var;
} public static void put(Object key, Object value) {
cache.put(key, value);
} class Person {
private String name;
private Integer age; public Person() {
} public Person(String name, Integer age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} @Override
public String toString() {
return "Person{" +
"名字='" + name + '\'' +
", 年纪=" + age +
'}';
}
} @Test
public void CacheTest() throws ExecutionException { Person person = new Person();
person.setAge(11);
person.setName("tSun");
System.out.println(CacheDemo.get("man"));
CacheDemo.put("man", new Person("hopg", 123));
System.out.println(CacheDemo.get("man"));
System.out.println(CacheDemo.get("man")); System.out.println(CacheDemo.get("person").toString());
CacheDemo.put("person", person);
System.out.println(CacheDemo.get("person").toString());
System.out.println(CacheDemo.get("person").toString()); System.out.println(CacheDemo.get("woman"));
CacheDemo.put("women", new Person("google", 666));
System.out.println(CacheDemo.get("woman"));
System.out.println(CacheDemo.get("woman"));
System.out.println(CacheDemo.get("man"));
}
}
结果:
如果没有值,就执行其他方式去获取值
Google.com.sg
Person{名字='hopg', 年纪=123}
Person{名字='hopg', 年纪=123}
如果没有值,就执行其他方式去获取值
Google.com.sg
Person{名字='tSun', 年纪=11}
Person{名字='tSun', 年纪=11}
如果没有值,就执行其他方式去获取值
Google.com.sg
Google.com.sg
Google.com.sg
Person{名字='hopg', 年纪=123}
方式二:
package info.sanaulla.cache; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.junit.Test; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-17 15:00
* Version: default 1.0.0
* Class description:
* <p>Cache Demo</p>
* <p/>
* *********************************************************
*/
public class CacheUtil { private static LoadingCache<Object, Object> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterAccess(24, TimeUnit.HOURS)
.recordStats()
.build(new CacheLoader<Object, Object>() { @Override
public Object load(Object key) throws Exception {
return key;
}
}); public static Object get(Object key) throws ExecutionException {
Object var = cache.get(key); if (var.equals(key)) { System.out.println("执行其他操作,查询该值");
/**执行其他操作,获取值**/
Object object = "Google.com.hk";
put(key, object);
} else {
System.out.println("从Cache中取值....");
}
return cache.get(key);
} public static void put(Object key, Object value) {
cache.put(key, value);
} class Person {
private String name;
private Integer age; public Person() {
} public Person(String name, Integer age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} @Override
public String toString() {
return "Person{" +
"名字='" + name + '\'' +
", 年纪=" + age +
'}';
}
} @Test
public void TestCache() throws ExecutionException { Person person = new Person();
person.setAge(11);
person.setName("tSun");
System.out.println(CacheUtil.get("man"));
CacheUtil.put("man", new Person("hopg", 123));
System.out.println(CacheUtil.get("man"));
System.out.println(CacheUtil.get("man")); System.out.println(CacheUtil.get("person").toString());
CacheUtil.put("person", person);
System.out.println(CacheUtil.get("person").toString());
System.out.println(CacheUtil.get("person").toString()); System.out.println(CacheUtil.get("woman"));
CacheUtil.put("women", new Person("google", 666));
System.out.println(CacheUtil.get("woman"));
System.out.println(CacheUtil.get("woman"));
System.out.println(CacheUtil.get("man"));
}
}
结果:
执行其他操作,查询该值
Google.com.hk
从Cache中取值....
Person{名字='hopg', 年纪=123}
从Cache中取值....
Person{名字='hopg', 年纪=123}
执行其他操作,查询该值
Google.com.hk
从Cache中取值....
Person{名字='tSun', 年纪=11}
从Cache中取值....
Person{名字='tSun', 年纪=11}
执行其他操作,查询该值
Google.com.hk
从Cache中取值....
Google.com.hk
从Cache中取值....
Google.com.hk
执行其他操作,查询该值
Google.com.hk
4. 如何和Spring结合使用
因为我们需要使用Spring的注解,所以需要重写Spring的一些接口,然后进行自定义.
4.1 首先简单了解一下@Cacheable,@CachePut,@CacheEvit
对于cache和数据操作进行一个功能对应,如下图.
cache sql
Cacheable --save/insert
关于Cacheable的简单说明:
@Cacheable注解,如果是类被注解,那么该类所有的方法下,如果在查询时,会先去查询缓存,没有的话,再去调用方法查询,
并且方法的返回值都会被缓存,如果是方法被注解,那么查询的时候,也会遵从先缓存,然后在方法,并且该方法的返回值都会被缓存.
CachePut --update/Insert
CacheEvit --remove/delete
4.2 首先我们需要实现接口Spring的BeanAware接口,以及InitializingBean接口,并实现FactoryBean接口,还有实现Spring的
AbstractTransactionSupportingCacheManager抽象类
过程大致如下:
1. 实现Cache接口
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheBuilderSpec;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper; import java.io.Serializable;
import java.util.concurrent.TimeUnit; import static com.google.common.base.Preconditions.checkNotNull; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-22 15:47
* Version: default 1.0.0
* Class description:
* <p/>
* *********************************************************
*/
public class GuavaCache implements Cache { private static final Object NULL_HOLDER = new NullHolder(); private final String name; private final com.google.common.cache.Cache<Object, Object> store; private final boolean allowNullValues; /**
* Create a new GuavaCache with the specified name.
*
* @param name the name of the cache
*/
public GuavaCache(String name) {
this(name, CacheBuilder.newBuilder(), true);
} /**
* Create a new GuavaCache with the specified name.
*
* @param name the name of the cache
* @param allowNullValues whether to accept and convert null values for this cache
*/
public GuavaCache(String name, boolean allowNullValues) {
this(name, CacheBuilder.newBuilder(), allowNullValues);
} /**
* Create a new GuavaCache using the specified name and {@link com.google.common.cache.CacheBuilderSpec specification}
*
* @param name the name of the cache
* @param spec the cache builder specification to use to build he cache
*/
public GuavaCache(String name, CacheBuilderSpec spec, boolean allowNullValues) {
this(name, CacheBuilder.from(spec), allowNullValues);
} /**
* Create a new GuavaCache using the specified name and {@link CacheBuilderSpec specification}
*
* @param name the name of the cache
* @param builder the cache builder to use to build the cache
*/
public GuavaCache(String name, CacheBuilder<Object, Object> builder, boolean allowNullValues) {
this.name = checkNotNull(name, "name is required");
this.allowNullValues = allowNullValues;
this.store = builder.maximumSize(CacheConstant.defaultCacheSize).
expireAfterWrite(CacheConstant.defaultCacheExpire, TimeUnit.MINUTES).
build();
} @Override
public String getName() {
return this.name;
} @Override
public com.google.common.cache.Cache<Object, Object> getNativeCache() {
return this.store;
} @Override
public ValueWrapper get(Object key) {
Object value = this.store.getIfPresent(key);
return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
} @Override
public void put(Object key, Object value) {
this.store.put(key, value);
} /**
* remove the key of object
*
* @param key
*/
@Override
public void evict(Object key) {
this.store.invalidate(key);
} /**
* clear all
*/
@Override
public void clear() {
this.store.invalidateAll();
} /**
* Convert the given value from the internal store to a user value
* returned from the get method (adapting {@code null}).
*
* @param storeValue the store value
* @return the value to return to the user
*/
protected Object fromStoreValue(Object storeValue) {
if (this.allowNullValues && storeValue == NULL_HOLDER) {
return null;
}
return storeValue;
} /**
* Convert the given user value, as passed into the put method,
* to a value in the internal store (adapting {@code null}).
*
* @param userValue the given user value
* @return the value to store
*/
protected Object toStoreValue(Object userValue) {
if (this.allowNullValues && userValue == null) {
return NULL_HOLDER;
}
return userValue;
} @SuppressWarnings("serial")
private static class NullHolder implements Serializable { }
}
2.实现Spring的FactoryBean,BeanAware,InitializingBean接口
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-22 16:00
* Version: default 1.0.0
* Class description:
* <p>{@link FactoryBean} for easy configuration of a {@link GuavaCache}.</p>
* <p/>
* *********************************************************
*/
public class GuavaCacheFactoryBean
implements FactoryBean<GuavaCache>, BeanNameAware, InitializingBean { private String name = ""; private boolean allowNullValues = true; private String spec; private GuavaCache cache; public void setName(String name) {
this.name = name;
} public void setAllowNullValues(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
} public void setSpec(String spec) {
this.spec = spec;
} @Override
public void setBeanName(String name) {
if (!StringUtils.hasLength(this.name)) {
this.name = name;
}
} @Override
public void afterPropertiesSet() throws Exception {
if (StringUtils.hasText(this.spec)) {
this.cache = new GuavaCache(this.name, CacheBuilder.from(spec), allowNullValues);
} else {
this.cache = new GuavaCache(this.name, allowNullValues);
}
} @Override
public GuavaCache getObject() throws Exception {
return this.cache;
} @Override
public Class<?> getObjectType() {
return GuavaCache.class;
} @Override
public boolean isSingleton() {
return true;
} }
3.实现Spring的Manager类
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
import org.springframework.util.StringUtils; import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.TimeUnit; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-22 16:09
* Version: default 1.0.0
* Class description:
* <p> {@link org.springframework.cache.CacheManager} implementation backed by {@link GuavaCache}.</p>
* <p/>
* *********************************************************
*/
public class GuavaCacheManager extends AbstractTransactionSupportingCacheManager {
private Collection<GuavaCache> caches; private String spec; private volatile CacheBuilder<Object, Object> cacheBuilder; private boolean allowNullValues = true; public GuavaCacheManager() {
} public void setCaches(Collection<GuavaCache> caches) {
this.caches = caches;
} public void setSpec(String spec) {
this.spec = spec;
} public String getSpec() {
return spec;
} public void setAllowNullValues(boolean allowNullValues) {
this.allowNullValues = allowNullValues;
} public boolean isAllowNullValues() {
return allowNullValues;
} @Override
protected Collection<? extends Cache> loadCaches() {
return (caches != null) ? caches : Collections.<GuavaCache>emptyList();
} @Override
public Cache getCache(String name) {
Cache cache = super.getCache(name);
if (cache == null) {
// create a new cache
cache = createGuavaCache(name); // add to collection of available caches
addCache(cache);
}
return cache;
} private GuavaCache createGuavaCache(String name) {
// create GuavaCache
return new GuavaCache(name, getCacheBuilder(), allowNullValues);
} private CacheBuilder<Object, Object> getCacheBuilder() {
if (cacheBuilder == null) {
synchronized (this) {
if (cacheBuilder == null) {
if (StringUtils.hasText(spec)) {
cacheBuilder = CacheBuilder.from(spec);
} else {
cacheBuilder =CacheBuilder.newBuilder();
} }
notify();
}
} return cacheBuilder;
} }
4.3 配置spring配置文件applicationContext.xml
<!--添加Cache-->
<!--添加一个注解驱动不要掉-->
<tx:annotation-driven/>
<!--使用spring注解去扫描需要加缓存地方的的包-->
<context:component-scan base-package="com.qunar.data.allinone.bus.testModel">
<context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
</context:component-scan>
<!-- cache Manager-->
<bean id="cacheManager" class="com.qunar.data.allinone.bus.cache.GuavaCacheManager">
<property name="caches">
<list>
<bean class="com.qunar.data.allinone.bus.cache.GuavaCacheFactoryBean" name="msg-cache"/>
</list>
</property>
</bean>
<!--cache的注解驱动包-->
<cache:annotation-driven/>
测试即可
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-22 19:50
* Version: default 1.0.0
* Class description:
* <p/>
* *********************************************************
*/
@Component
public class TestName { @Cacheable(value = "msg-cache")
public String getName(String con) {
System.out.println("缓存中没有找到信息");
return con;
}
}
import com.qunar.data.allinone.bus.testModel.TestName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.annotation.Resource; /**
* *********************************************************
* <p/>
* Author: XiJun.Gong
* Date: 2016-08-22 19:30
* Version: default 1.0.0
* Class description:
* <p/>
* *********************************************************
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class CacheTest { @Resource TestName testName; @Test
public void testName() {
String username = "xijun.gong";
for (int i = 0; i < 10; i++) {
System.out.println("++++++++++++++++打印结果: " + testName.getName(username));
}
}
}
缓存中没有找到信息
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
++++++++++++++++打印结果: 王小二
5. 扩展
在github上看到一篇关于,对于overflow时候,将数据写入到文件系统的例子,还不错,如果有这方面的需求可以看看.
地址:https://github.com/raphw/guava-cache-overflow-extension
Guava------------Cache使用方法的更多相关文章
- Spring cache简单使用guava cache
Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...
- [Java 缓存] Java Cache之 Guava Cache的简单应用.
前言 今天第一次使用MarkDown的形式发博客. 准备记录一下自己对Guava Cache的认识及项目中的实际使用经验. 一: 什么是Guava Guava工程包含了若干被Google的 Java项 ...
- Guava学习笔记:Guava cache
缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间. 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用 ...
- guava cache
适用场景 缓存在很多场景下都是相当有用的.例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存. Guava Cache与ConcurrentMap很相似,但 ...
- 第七章 企业项目开发--本地缓存guava cache
1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分两种:本地缓存和分布式缓存. 常用的本地缓存是guava cache,本章主要介绍guava ...
- (翻译)Google Guava Cache
翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering G ...
- 是什么让spring 5放弃了使用Guava Cache?
一路走来,Spring社区从刚开始的核心模块一直发展到现在,最近Sping5也完成了M5的发布, 相信不久之后第一个RELEASE版本也会发布.里面有很多特性是和即将要发布的JAVA 9息息相关的.今 ...
- Guava Cache源码解析
概述: 本次主要是分析cache的源码,基本概念官方简介即可. 基本类图: 在官方的文档说明中,Guava Cache实现了三种加载缓存的方式: LoadingCache在构建缓存的时候,使用buil ...
- google guava cache缓存基本使用讲解
代码地址:https://github.com/vikde/demo-guava-cache 一.简介 guava cache是google guava中的一个内存缓存模块,用于将数据缓存到JVM内存 ...
- guava cache使用和源码分析
guava cache的优点和使用场景,用来判断业务中是否适合使用此缓存 介绍常用的方法,并给出示例,作为使用的参考 深入解读源码. guava简介 guava cache是一个本地缓存.有以下优点: ...
随机推荐
- Card Flip
卡牌效果:O(∩_∩)O,只做了webkit浏览器的效果,请用chrome~ 1.首先呢,先用一个框框把卡牌包住,然后呢,搞两个子元素作为卡牌正反面.当然咯,反面是看不见滴~ <section ...
- [转]struct.pack 用法手记
原文:http://hi.baidu.com/tibelf/item/8b463d15edfdf10bd1d66d83 看到在进行c格式的二进制文件读取的过程中,用到了struct.unpack方法, ...
- iTunes
我们的电脑都要下载比较好的显卡那项 https://support.apple.com/zh_CN/downloads/itunes
- JavaScriptCore 使用
JavaScriptCore JavaScriptCore是webkit的一个重要组成部分,主要是对JS进行解析和提供执行环境.代码是开源的,可以下下来看看(源码).iOS7后苹果在iPhone平台推 ...
- java中的23中设计模式(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Linux环境下Android开发环境的搭建
本文主要介绍在Ubuntu下Android开发环境的搭建,所使用的IDE为Eclipse(Android Studio同理,且可省去配置SDK以及安装adt插件的步骤). 1.安装JDK (1)JDK ...
- java读取输入流
java读取输入流两种 private static byte[] readStream(InputStream in){ if(in==null){ return null; } byte[] bu ...
- C++多线程の8*2重多线程创建方式
- python 学习笔记二十 django项目bbs论坛
项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...
- js 方法封装实例
(function(){ if(windows.Mr_2_B){windows.Mr_2_B={};} function trim(txt){return txt.replace(/(^\s*|(\s ...