1.Guava------------Cache使用方法
来源:互联网 发布:药品数据查询 编辑:程序博客网 时间:2024/06/10 08:27
http://www.cnblogs.com/gongxijun/p/5781108.html
简单从这几个方面描述一下如何使用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
方式一:
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 }
结果:
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.sg11 Google.com.sg12 Google.com.sg13 Person{名字='hopg', 年纪=123}
方式二:
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 }
结果:
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.hk15 从Cache中取值....16 Google.com.hk17 从Cache中取值....18 Google.com.hk19 执行其他操作,查询该值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接口
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 key100 */101 @Override102 public void evict(Object key) {103 this.store.invalidate(key);104 }105 106 /**107 * clear all108 */109 @Override110 public void clear() {111 this.store.invalidateAll();112 }113 114 /**115 * Convert the given value from the internal store to a user value116 * returned from the get method (adapting {@code null}).117 *118 * @param storeValue the store value119 * @return the value to return to the user120 */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 value133 * @return the value to store134 */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接口
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.Gong11 * Date: 2016-08-22 16:0012 * Version: default 1.0.013 * Class description:14 * <p>{@link FactoryBean} for easy configuration of a {@link GuavaCache}.</p>15 * <p/>16 * *********************************************************17 */18 public class GuavaCacheFactoryBean19 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 @Override42 public void setBeanName(String name) {43 if (!StringUtils.hasLength(this.name)) {44 this.name = name;45 }46 }47 48 @Override49 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 @Override58 public GuavaCache getObject() throws Exception {59 return this.cache;60 }61 62 @Override63 public Class<?> getObjectType() {64 return GuavaCache.class;65 }66 67 @Override68 public boolean isSingleton() {69 return true;70 }71 72 }
3.实现Spring的Manager类
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.Gong15 * Date: 2016-08-22 16:0916 * Version: default 1.0.017 * 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 @Override55 protected Collection<? extends Cache> loadCaches() {56 return (caches != null) ? caches : Collections.<GuavaCache>emptyList();57 }58 59 @Override60 public Cache getCache(String name) {61 Cache cache = super.getCache(name);62 if (cache == null) {63 // create a new cache64 cache = createGuavaCache(name);65 66 // add to collection of available caches67 addCache(cache);68 }69 return cache;70 }71 72 private GuavaCache createGuavaCache(String name) {73 // create GuavaCache74 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
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/>
测试即可
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:5010 * Version: default 1.0.011 * Class description:12 * <p/>13 * *********************************************************14 */15 @Component16 public class TestName {17 18 @Cacheable(value = "msg-cache")19 public String getName(String con) {20 System.out.println("缓存中没有找到信息");21 return con;22 }23 }
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.Gong13 * Date: 2016-08-22 19:3014 * Version: default 1.0.015 * Class description:16 * <p/>17 * *********************************************************18 */19 @RunWith(SpringJUnit4ClassRunner.class)20 @ContextConfiguration(value = "classpath:applicationContext.xml")21 public class CacheTest {22 23 24 @Resource2526 TestName testName;27 28 @Test29 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 }
缓存中没有找到信息++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二++++++++++++++++打印结果: 王小二
5. 扩展
在github上看到一篇关于,对于overflow时候,将数据写入到文件系统的例子,还不错,如果有这方面的需求可以看看.
地址:https://github.com/raphw/guava-cache-overflow-extension
http://www.cnblogs.com/gongxijun/p/5781108.html
- 1.Guava------------Cache使用方法
- guava cache
- Guava cache
- Guava-cache
- Guava Cache
- guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Guava学习笔记:Guava cache
- Cache高速缓存guava-libraries Cache
- Guava Cache之Cache接口
- guava cache学习
- guava cache使用例子
- js调用函数时加括号与不加括号的区别
- request的请求参数获取方式
- Angular2踩坑之自定义Pipe管道
- 字符串模板
- 如何获得当前系统时间
- 1.Guava------------Cache使用方法
- 南阳OJ 题目24:素数距离问题
- windows下安装Linux(Ubuntu)系统
- 需要了解的基本概念——特征、训练集、样例等
- 模板的分离编译
- Ubuntu下安装tensorFlow遇到的问题和解决方案
- 【SegNet】SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image
- 【商城开发七】BaseActivity/BaseFragment篇
- uva 11082 Matrix Decompressing