简单从这几个方面描述一下如何使用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使用方法的更多相关文章

  1. Spring cache简单使用guava cache

    Spring cache简单使用 前言 spring有一套和各种缓存的集成方式.类似于sl4j,你可以选择log框架实现,也一样可以实现缓存实现,比如ehcache,guava cache. [TOC ...

  2. [Java 缓存] Java Cache之 Guava Cache的简单应用.

    前言 今天第一次使用MarkDown的形式发博客. 准备记录一下自己对Guava Cache的认识及项目中的实际使用经验. 一: 什么是Guava Guava工程包含了若干被Google的 Java项 ...

  3. Guava学习笔记:Guava cache

    缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间. 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用 ...

  4. guava cache

    适用场景 缓存在很多场景下都是相当有用的.例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存. Guava Cache与ConcurrentMap很相似,但 ...

  5. 第七章 企业项目开发--本地缓存guava cache

    1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分两种:本地缓存和分布式缓存. 常用的本地缓存是guava cache,本章主要介绍guava ...

  6. (翻译)Google Guava Cache

    翻译自Google Guava Cache This Post is a continuation of my series on Google Guava, this time covering G ...

  7. 是什么让spring 5放弃了使用Guava Cache?

    一路走来,Spring社区从刚开始的核心模块一直发展到现在,最近Sping5也完成了M5的发布, 相信不久之后第一个RELEASE版本也会发布.里面有很多特性是和即将要发布的JAVA 9息息相关的.今 ...

  8. Guava Cache源码解析

    概述: 本次主要是分析cache的源码,基本概念官方简介即可. 基本类图: 在官方的文档说明中,Guava Cache实现了三种加载缓存的方式: LoadingCache在构建缓存的时候,使用buil ...

  9. google guava cache缓存基本使用讲解

    代码地址:https://github.com/vikde/demo-guava-cache 一.简介 guava cache是google guava中的一个内存缓存模块,用于将数据缓存到JVM内存 ...

  10. guava cache使用和源码分析

    guava cache的优点和使用场景,用来判断业务中是否适合使用此缓存 介绍常用的方法,并给出示例,作为使用的参考 深入解读源码. guava简介 guava cache是一个本地缓存.有以下优点: ...

随机推荐

  1. [Java Web]Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors

    手机客户端向服务器提交Http请求时,Tomcat抛出错误: 十二月 31, 2014 2:32:45 下午 org.apache.coyote.http11.AbstractHttp11Proces ...

  2. Python ---list,dict,str

    Python中定义常量 都用大写 Pip 安装python第三方模块的命令  一般默认都放在/python27/lib/site-pak List.count(‘元素’)-------------统计 ...

  3. 笔记汇总.md

    ```javascript 1.js对象,value的值取不到,试着将引入的js文件放到body的后面 $("input[type='time']").change( functi ...

  4. 市面上主流服务器简单介绍(apache、IIS、tomcat..)

    apache:apache(阿帕奇)的具体介绍可以参看apache的网站(http://www.apache.org/),或者在网上随便搜搜吧.apache是世界使用排名第一的web服务器软件:它可以 ...

  5. 如何站在使用者的角度来设计SDK-微信公众号开发SDK(消息处理)设计之抛砖引玉

    0.SDK之必备的基本素质 在项目中免不了要用到各种各样的第三方的sdk,在我现在的工作中就在公司内部积累了各种各样的的公共库(基于.net的,基于silverlight的等等),托管到了内部的nug ...

  6. Mybatis Generator生成工具配置文件详解

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration ...

  7. 使用JavaScript访问子节点方法elementNode.childNodes时,需要注意的地方

    有这样一个HTML结构 <div> javascript <p>javascript</p> <div>jQuery</div> <h ...

  8. linux下的a.out文件

       当然这里,我更重要的是强调这个什么段,什么段.这以前就知道.但其实是对一个可以执行的c语言程序的分析.就好比你分析一篇作文.有标题.有段落. .out文件就是扩展名为out的文件,它本身不代表任 ...

  9. java:IO流学习小结

    可以看以下内容学习一下: http://blog.csdn.net/zzp_403184692/article/details/8057693

  10. Oracle(DML)

    数据操作语言: insert update delete 事务控制语言: commit rollback savepoint 1.insert语句 两种格式: 直接插入 子查询插入 1. 直接插入基本 ...