前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Guava------------Cache使用方法

Guava------------Cache使用方法

作者头像
Gxjun
发布2018-03-27 11:06:29
3K0
发布2018-03-27 11:06:29
举报
文章被收录于专栏:mlml

    简单从这几个方面描述一下如何使用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

    方式一:

代码语言:javascript
复制
  1 package info.sanaulla.cache;
  2 
  3 import com.google.common.cache.Cache;
  4 import com.google.common.cache.CacheBuilder;
  5 import org.junit.Test;
  6 
  7 import java.util.concurrent.Callable;
  8 import java.util.concurrent.ExecutionException;
  9 import java.util.concurrent.TimeUnit;
 10 
 11 /**
 12  * *********************************************************
 13  * <p/>
 14  * Author:     XiJun.Gong
 15  * Date:       2016-08-17 16:59
 16  * Version:    default 1.0.0
 17  * Class description:
 18  * <p/>
 19  * *********************************************************
 20  */
 21 public class CacheDemo {
 22     private static Cache<Object, Object> cache = CacheBuilder.newBuilder()
 23             .maximumSize(100).expireAfterWrite(24, TimeUnit.HOURS)
 24             .recordStats()
 25             .build();
 26 
 27     public static Object get(Object key) throws ExecutionException {
 28 
 29         Object var = cache.get(key, new Callable<Object>() {
 30             @Override
 31             public Object call() throws Exception {
 32                 System.out.println("如果没有值,就执行其他方式去获取值");
 33                 String var = "Google.com.sg";
 34                 return var;
 35             }
 36         });
 37         return var;
 38     }
 39 
 40     public static void put(Object key, Object value) {
 41         cache.put(key, value);
 42     }
 43 
 44     class Person {
 45         private String name;
 46         private Integer age;
 47 
 48         public Person() {
 49         }
 50 
 51         public Person(String name, Integer age) {
 52             this.name = name;
 53             this.age = age;
 54         }
 55 
 56         public String getName() {
 57             return name;
 58         }
 59 
 60         public void setName(String name) {
 61             this.name = name;
 62         }
 63 
 64         public Integer getAge() {
 65             return age;
 66         }
 67 
 68         public void setAge(Integer age) {
 69             this.age = age;
 70         }
 71 
 72         @Override
 73         public String toString() {
 74             return "Person{" +
 75                     "名字='" + name + '\'' +
 76                     ", 年纪=" + age +
 77                     '}';
 78         }
 79     }
 80 
 81     @Test
 82     public void CacheTest() throws ExecutionException {
 83 
 84         Person person = new Person();
 85         person.setAge(11);
 86         person.setName("tSun");
 87         System.out.println(CacheDemo.get("man"));
 88         CacheDemo.put("man", new Person("hopg", 123));
 89         System.out.println(CacheDemo.get("man"));
 90         System.out.println(CacheDemo.get("man"));
 91 
 92         System.out.println(CacheDemo.get("person").toString());
 93         CacheDemo.put("person", person);
 94         System.out.println(CacheDemo.get("person").toString());
 95         System.out.println(CacheDemo.get("person").toString());
 96 
 97         System.out.println(CacheDemo.get("woman"));
 98         CacheDemo.put("women", new Person("google", 666));
 99         System.out.println(CacheDemo.get("woman"));
100         System.out.println(CacheDemo.get("woman"));
101         System.out.println(CacheDemo.get("man"));
102     }
103 }

结果:

代码语言:javascript
复制
 1 如果没有值,就执行其他方式去获取值
 2 Google.com.sg
 3 Person{名字='hopg', 年纪=123}
 4 Person{名字='hopg', 年纪=123}
 5 如果没有值,就执行其他方式去获取值
 6 Google.com.sg
 7 Person{名字='tSun', 年纪=11}
 8 Person{名字='tSun', 年纪=11}
 9 如果没有值,就执行其他方式去获取值
10 Google.com.sg
11 Google.com.sg
12 Google.com.sg
13 Person{名字='hopg', 年纪=123}

 方式二:

代码语言:javascript
复制
  1 package info.sanaulla.cache;
  2 
  3 import com.google.common.cache.CacheBuilder;
  4 import com.google.common.cache.CacheLoader;
  5 import com.google.common.cache.LoadingCache;
  6 import org.junit.Test;
  7 
  8 import java.util.concurrent.ExecutionException;
  9 import java.util.concurrent.TimeUnit;
 10 
 11 /**
 12  * *********************************************************
 13  * <p/>
 14  * Author:     XiJun.Gong
 15  * Date:       2016-08-17 15:00
 16  * Version:    default 1.0.0
 17  * Class description:
 18  * <p>Cache Demo</p>
 19  * <p/>
 20  * *********************************************************
 21  */
 22 public class CacheUtil {
 23 
 24 
 25     private static LoadingCache<Object, Object> cache = CacheBuilder.newBuilder()
 26             .maximumSize(2)
 27             .expireAfterAccess(24, TimeUnit.HOURS)
 28             .recordStats()
 29             .build(new CacheLoader<Object, Object>() {
 30 
 31                 @Override
 32                 public Object load(Object key) throws Exception {
 33                     return key;
 34                 }
 35             });
 36 
 37     public static Object get(Object key) throws ExecutionException {
 38         Object var = cache.get(key);
 39 
 40         if (var.equals(key)) {
 41 
 42             System.out.println("执行其他操作,查询该值");
 43             /**执行其他操作,获取值**/
 44             Object object = "Google.com.hk";
 45             put(key, object);
 46         } else {
 47             System.out.println("从Cache中取值....");
 48         }
 49         return cache.get(key);
 50     }
 51 
 52     public static void put(Object key, Object value) {
 53         cache.put(key, value);
 54     }
 55 
 56     class Person {
 57         private String name;
 58         private Integer age;
 59 
 60         public Person() {
 61         }
 62 
 63         public Person(String name, Integer age) {
 64             this.name = name;
 65             this.age = age;
 66         }
 67 
 68         public String getName() {
 69             return name;
 70         }
 71 
 72         public void setName(String name) {
 73             this.name = name;
 74         }
 75 
 76         public Integer getAge() {
 77             return age;
 78         }
 79 
 80         public void setAge(Integer age) {
 81             this.age = age;
 82         }
 83 
 84         @Override
 85         public String toString() {
 86             return "Person{" +
 87                     "名字='" + name + '\'' +
 88                     ", 年纪=" + age +
 89                     '}';
 90         }
 91     }
 92 
 93     @Test
 94     public void TestCache() throws ExecutionException {
 95 
 96         Person person = new Person();
 97         person.setAge(11);
 98         person.setName("tSun");
 99         System.out.println(CacheUtil.get("man"));
100         CacheUtil.put("man", new Person("hopg", 123));
101         System.out.println(CacheUtil.get("man"));
102         System.out.println(CacheUtil.get("man"));
103 
104         System.out.println(CacheUtil.get("person").toString());
105         CacheUtil.put("person", person);
106         System.out.println(CacheUtil.get("person").toString());
107         System.out.println(CacheUtil.get("person").toString());
108 
109         System.out.println(CacheUtil.get("woman"));
110         CacheUtil.put("women", new Person("google", 666));
111         System.out.println(CacheUtil.get("woman"));
112         System.out.println(CacheUtil.get("woman"));
113         System.out.println(CacheUtil.get("man"));
114     }
115 }

结果:

代码语言:javascript
复制
 1 执行其他操作,查询该值
 2 Google.com.hk
 3 从Cache中取值....
 4 Person{名字='hopg', 年纪=123}
 5 从Cache中取值....
 6 Person{名字='hopg', 年纪=123}
 7 执行其他操作,查询该值
 8 Google.com.hk
 9 从Cache中取值....
10 Person{名字='tSun', 年纪=11}
11 从Cache中取值....
12 Person{名字='tSun', 年纪=11}
13 执行其他操作,查询该值
14 Google.com.hk
15 从Cache中取值....
16 Google.com.hk
17 从Cache中取值....
18 Google.com.hk
19 执行其他操作,查询该值
20 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接口

代码语言:javascript
复制
  1 import com.google.common.cache.CacheBuilder;
  2 import com.google.common.cache.CacheBuilderSpec;
  3 import org.springframework.cache.Cache;
  4 import org.springframework.cache.support.SimpleValueWrapper;
  5 
  6 import java.io.Serializable;
  7 import java.util.concurrent.TimeUnit;
  8 
  9 import static com.google.common.base.Preconditions.checkNotNull;
 10 
 11 /**
 12  * *********************************************************
 13  * <p/>
 14  * Author:     XiJun.Gong
 15  * Date:       2016-08-22 15:47
 16  * Version:    default 1.0.0
 17  * Class description:
 18  * <p/>
 19  * *********************************************************
 20  */
 21 public class GuavaCache implements Cache {
 22 
 23 
 24     private static final Object NULL_HOLDER = new NullHolder();
 25 
 26     private final String name;
 27 
 28     private final com.google.common.cache.Cache<Object, Object> store;
 29 
 30     private final boolean allowNullValues;
 31 
 32     /**
 33      * Create a new GuavaCache with the specified name.
 34      *
 35      * @param name the name of the cache
 36      */
 37     public GuavaCache(String name) {
 38         this(name, CacheBuilder.newBuilder(), true);
 39     }
 40 
 41     /**
 42      * Create a new GuavaCache with the specified name.
 43      *
 44      * @param name            the name of the cache
 45      * @param allowNullValues whether to accept and convert null values for this cache
 46      */
 47     public GuavaCache(String name, boolean allowNullValues) {
 48         this(name, CacheBuilder.newBuilder(), allowNullValues);
 49     }
 50 
 51     /**
 52      * Create a new GuavaCache using the specified name and {@link com.google.common.cache.CacheBuilderSpec specification}
 53      *
 54      * @param name the name of the cache
 55      * @param spec the cache builder specification to use to build he cache
 56      */
 57     public GuavaCache(String name, CacheBuilderSpec spec, boolean allowNullValues) {
 58         this(name, CacheBuilder.from(spec), allowNullValues);
 59     }
 60 
 61     /**
 62      * Create a new GuavaCache using the specified name and {@link CacheBuilderSpec specification}
 63      *
 64      * @param name    the name of the cache
 65      * @param builder the cache builder to use to build the cache
 66      */
 67     public GuavaCache(String name, CacheBuilder<Object, Object> builder, boolean allowNullValues) {
 68         this.name = checkNotNull(name, "name is required");
 69         this.allowNullValues = allowNullValues;
 70         this.store = builder.maximumSize(CacheConstant.defaultCacheSize).
 71                 expireAfterWrite(CacheConstant.defaultCacheExpire, TimeUnit.MINUTES).
 72                 build();
 73     }
 74 
 75     @Override
 76     public String getName() {
 77         return this.name;
 78     }
 79 
 80     @Override
 81     public com.google.common.cache.Cache<Object, Object> getNativeCache() {
 82         return this.store;
 83     }
 84 
 85     @Override
 86     public ValueWrapper get(Object key) {
 87         Object value = this.store.getIfPresent(key);
 88         return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null);
 89     }
 90 
 91     @Override
 92     public void put(Object key, Object value) {
 93         this.store.put(key, value);
 94     }
 95 
 96     /**
 97      * remove the key of object
 98      *
 99      * @param key
100      */
101     @Override
102     public void evict(Object key) {
103         this.store.invalidate(key);
104     }
105 
106     /**
107      * clear all
108      */
109     @Override
110     public void clear() {
111         this.store.invalidateAll();
112     }
113 
114     /**
115      * Convert the given value from the internal store to a user value
116      * returned from the get method (adapting {@code null}).
117      *
118      * @param storeValue the store value
119      * @return the value to return to the user
120      */
121     protected Object fromStoreValue(Object storeValue) {
122         if (this.allowNullValues && storeValue == NULL_HOLDER) {
123             return null;
124         }
125         return storeValue;
126     }
127 
128     /**
129      * Convert the given user value, as passed into the put method,
130      * to a value in the internal store (adapting {@code null}).
131      *
132      * @param userValue the given user value
133      * @return the value to store
134      */
135     protected Object toStoreValue(Object userValue) {
136         if (this.allowNullValues && userValue == null) {
137             return NULL_HOLDER;
138         }
139         return userValue;
140     }
141 
142 
143     @SuppressWarnings("serial")
144     private static class NullHolder implements Serializable {
145 
146     }
147 }

2.实现Spring的FactoryBean,BeanAware,InitializingBean接口

代码语言:javascript
复制
 1 import com.google.common.cache.CacheBuilder;
 2 import org.springframework.beans.factory.BeanNameAware;
 3 import org.springframework.beans.factory.FactoryBean;
 4 import org.springframework.beans.factory.InitializingBean;
 5 import org.springframework.util.StringUtils;
 6 
 7 /**
 8  * *********************************************************
 9  * <p/>
10  * Author:     XiJun.Gong
11  * Date:       2016-08-22 16:00
12  * Version:    default 1.0.0
13  * Class description:
14  * <p>{@link FactoryBean} for easy configuration of a {@link GuavaCache}.</p>
15  * <p/>
16  * *********************************************************
17  */
18 public class GuavaCacheFactoryBean
19         implements FactoryBean<GuavaCache>, BeanNameAware, InitializingBean {
20 
21     private String name = "";
22 
23     private boolean allowNullValues = true;
24 
25     private String spec;
26 
27     private GuavaCache cache;
28 
29     public void setName(String name) {
30         this.name = name;
31     }
32 
33     public void setAllowNullValues(boolean allowNullValues) {
34         this.allowNullValues = allowNullValues;
35     }
36 
37     public void setSpec(String spec) {
38         this.spec = spec;
39     }
40 
41     @Override
42     public void setBeanName(String name) {
43         if (!StringUtils.hasLength(this.name)) {
44             this.name = name;
45         }
46     }
47 
48     @Override
49     public void afterPropertiesSet() throws Exception {
50         if (StringUtils.hasText(this.spec)) {
51             this.cache = new GuavaCache(this.name, CacheBuilder.from(spec), allowNullValues);
52         } else {
53             this.cache = new GuavaCache(this.name, allowNullValues);
54         }
55     }
56 
57     @Override
58     public GuavaCache getObject() throws Exception {
59         return this.cache;
60     }
61 
62     @Override
63     public Class<?> getObjectType() {
64         return GuavaCache.class;
65     }
66 
67     @Override
68     public boolean isSingleton() {
69         return true;
70     }
71 
72 }

3.实现Spring的Manager类

代码语言:javascript
复制
 1 import com.google.common.cache.CacheBuilder;
 2 import com.google.common.cache.CacheLoader;
 3 import org.springframework.cache.Cache;
 4 import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
 5 import org.springframework.util.StringUtils;
 6 
 7 import java.util.Collection;
 8 import java.util.Collections;
 9 import java.util.concurrent.TimeUnit;
10 
11 /**
12  * *********************************************************
13  * <p/>
14  * Author:     XiJun.Gong
15  * Date:       2016-08-22 16:09
16  * Version:    default 1.0.0
17  * Class description:
18  * <p> {@link org.springframework.cache.CacheManager} implementation backed by {@link GuavaCache}.</p>
19  * <p/>
20  * *********************************************************
21  */
22 public class GuavaCacheManager extends AbstractTransactionSupportingCacheManager {
23     private Collection<GuavaCache> caches;
24 
25     private String spec;
26 
27     private volatile CacheBuilder<Object, Object> cacheBuilder;
28 
29     private boolean allowNullValues = true;
30 
31     public GuavaCacheManager() {
32     }
33 
34     public void setCaches(Collection<GuavaCache> caches) {
35         this.caches = caches;
36     }
37 
38     public void setSpec(String spec) {
39         this.spec = spec;
40     }
41 
42     public String getSpec() {
43         return spec;
44     }
45 
46     public void setAllowNullValues(boolean allowNullValues) {
47         this.allowNullValues = allowNullValues;
48     }
49 
50     public boolean isAllowNullValues() {
51         return allowNullValues;
52     }
53 
54     @Override
55     protected Collection<? extends Cache> loadCaches() {
56         return (caches != null) ? caches : Collections.<GuavaCache>emptyList();
57     }
58 
59     @Override
60     public Cache getCache(String name) {
61         Cache cache = super.getCache(name);
62         if (cache == null) {
63             // create a new cache
64             cache = createGuavaCache(name);
65 
66             // add to collection of available caches
67             addCache(cache);
68         }
69         return cache;
70     }
71 
72     private GuavaCache createGuavaCache(String name) {
73         // create GuavaCache
74         return new GuavaCache(name, getCacheBuilder(), allowNullValues);
75     }
76 
77     private CacheBuilder<Object, Object> getCacheBuilder() {
78         if (cacheBuilder == null) {
79             synchronized (this) {
80                 if (cacheBuilder == null) {
81                     if (StringUtils.hasText(spec)) {
82                         cacheBuilder = CacheBuilder.from(spec);
83                     } else {
84                         cacheBuilder =CacheBuilder.newBuilder();
85                     }
86 
87                 }
88                 notify();
89             }
90         }
91 
92         return cacheBuilder;
93     }
94 
95 }

    4.3 配置spring配置文件applicationContext.xml

代码语言:javascript
复制
 1     <!--添加Cache-->
 2     <!--添加一个注解驱动不要掉-->
 3     <tx:annotation-driven/>
 4     <!--使用spring注解去扫描需要加缓存地方的的包-->
 5     <context:component-scan base-package="com.qunar.data.allinone.bus.testModel">
 6         <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
 7     </context:component-scan>
 8     <!-- cache Manager-->
 9     <bean id="cacheManager" class="com.qunar.data.allinone.bus.cache.GuavaCacheManager">
10         <property name="caches">
11             <list>
12                 <bean class="com.qunar.data.allinone.bus.cache.GuavaCacheFactoryBean" name="msg-cache"/>
13             </list>
14         </property>
15     </bean>
16     <!--cache的注解驱动包-->
17     <cache:annotation-driven/>

测试即可

代码语言:javascript
复制
 1 import org.springframework.cache.annotation.Cacheable;
 2 import org.springframework.stereotype.Component;
 3 import org.springframework.stereotype.Service;
 4 
 5 /**
 6  * *********************************************************
 7  * <p/>
 8  * Author:     XiJun.Gong
 9  * Date:       2016-08-22 19:50
10  * Version:    default 1.0.0
11  * Class description:
12  * <p/>
13  * *********************************************************
14  */
15 @Component
16 public class TestName {
17 
18     @Cacheable(value = "msg-cache")
19     public String getName(String con) {
20         System.out.println("缓存中没有找到信息");
21         return con;
22     }
23 }
代码语言:javascript
复制
 1 import com.qunar.data.allinone.bus.testModel.TestName;
 2 import org.junit.Test;
 3 import org.junit.runner.RunWith;
 4 import org.springframework.test.context.ContextConfiguration;
 5 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 6 
 7 import javax.annotation.Resource;
 8 
 9 /**
10  * *********************************************************
11  * <p/>
12  * Author:     XiJun.Gong
13  * Date:       2016-08-22 19:30
14  * Version:    default 1.0.0
15  * Class description:
16  * <p/>
17  * *********************************************************
18  */
19 @RunWith(SpringJUnit4ClassRunner.class)
20 @ContextConfiguration(value = "classpath:applicationContext.xml")
21 public class CacheTest {
22 
23 
24     @Resource
25
26     TestName testName;
27 
28     @Test
29     public void testName() {
30         String username = "xijun.gong";
31         for (int i = 0; i < 10; i++) {
32             System.out.println("++++++++++++++++打印结果:   " + testName.getName(username));
33         }
34     }
35 }
代码语言:javascript
复制
缓存中没有找到信息
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二
++++++++++++++++打印结果:   王小二

 5. 扩展 

     在github上看到一篇关于,对于overflow时候,将数据写入到文件系统的例子,还不错,如果有这方面的需求可以看看.

地址:https://github.com/raphw/guava-cache-overflow-extension

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-08-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档