Spring Cache

2019-01-17  本文已影响0人  Minato666

在我们日常编码中,cache是很常见的,在没有使用spring cache之前,我们可能会使用下面这种代码来实现cache:

public class MyCacheManager<T> { 
  private Map<String,T> cache = 
      new ConcurrentHashMap<String,T>(); 
  
  public T getValue(Object key) { 
    return cache.get(key); 
  } 
  
  public void addOrUpdateCache(String key,T value) { 
    cache.put(key, value); 
  } 
  
  public void evictCache(String key) {// 根据 key 来删除缓存中的一条记录
    if(cache.containsKey(key)) { 
      cache.remove(key); 
    } 
  } 
  
  public void evictCache() {// 清空缓存中的所有记录
    cache.clear(); 
  } 
}

然后在使用的地方使用该cacheManage 缓存和获取数据。缺点就是和业务代码耦合度比较高,不灵活,不能灵活切换第三方缓存模块。而如果使用Spring Cahce就可以杜绝这些问题。
Spring Cache使用非常简单,这里我们使用ehcache作为spring cache的cache manager。由于spring 自带的cachemanager不支持缓存定期失效刷新,所以我们采用ehcache。

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.8.2</version>
        </dependency>
<cache:annotation-driven/>
<bean id="ehcache"  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
          p:config-location="classpath:ehcache.xml"
          p:shared="true"/>

    <bean id="cacheManager"
          class="org.springframework.cache.ehcache.EhCacheCacheManager"
          p:cache-manager-ref="ehcache"/>

classpath下加入ehcache.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false">
   <!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
   <diskStore path="java.io.tmpdir"/>

   <cache name="SystemConfigCache"
          maxElementsInMemory="1000"
          eternal="false"
          overflowToDisk="false"
          timeToIdleSeconds="600"
          timeToLiveSeconds="700"/>

</ehcache>

注意其中的cache name,这个是我们后面配置要用到的,

eternal:true表示对象永不过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds属性,默认为false。
timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性 值,这个对象就会过期,EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限 期地处于空闲状态
timeToLiveSeconds:设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有 效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
package com.oocl.ir4.sps.service.cache;

import com.oocl.ir4.sps.dao.common.SystemConfigDao;
import com.oocl.ir4.sps.entity.common.SystemConfig;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

import javax.annotation.Resource;

@CacheConfig(cacheNames = "SystemConfigCache")
public class SystemConfigCache {

    @Resource
    SystemConfigDao systemConfigDao;


    @Cacheable( key = "'SystemConfig_' + #key")
    public SystemConfig getConfigByKey(String key) {
        System.out.print("read from db ===================================");
        return systemConfigDao.findSystemConfigByKey(key);
    }

    @CacheEvict(allEntries = true)
    public void reload() {

    }

}

在类上配置了cacheNames,就是之前我们在ehcache.xml配置的。
其中的getConfigByKey 这个方法,我们给它加了一个annotation,@Cacheable 这个就表示我要把该方法的返回值缓存下来,key就是我们指定的格式”SystemConfig_ + 传入的参数key”.

如果我们想清空缓存,可以使用@CacheEvict(allEntries = true) ,也就是代码中reload方法。

运行下面测试:

@Test
    public void systemConfig() {
        System.out.println("first query");
        SystemConfig systemConfig = systemConfigCache.getConfigByKey(EmailConfig.KEY);
        System.out.println(JsonUtil.writeValueAsPrettyString(systemConfig));
        System.out.println("second query");
        SystemConfig systemConfig1 = systemConfigCache.getConfigByKey(EmailConfig.KEY);
        System.out.println(JsonUtil.writeValueAsPrettyString(systemConfig1));
    }

获得结果:

first query
read from db ===================================
{
  "id" : {
    "time" : 1547704819000,
    "timestamp" : 1547704819,
    "date" : 1547704819000,
    "new" : false,
    "inc" : 493821772,
    "machine" : 1078273087,
    "timeSecond" : 1547704819
  },
  "key" : "EMAIL_CONFIG",
  "value" : "{\"aliyunEmailDomains\":[\"stp.com\"]}"
}
second query
{
  "id" : {
    "time" : 1547704819000,
    "timestamp" : 1547704819,
    "date" : 1547704819000,
    "new" : false,
    "inc" : 493821772,
    "machine" : 1078273087,
    "timeSecond" : 1547704819
  },
  "key" : "EMAIL_CONFIG",
  "value" : "{\"aliyunEmailDomains\":[\"stp.com\"]}"
}

可以看到第一次是从DB中获取数据,第二次是从cache中获取数据。

上一篇下一篇

猜你喜欢

热点阅读