Spring Cache与Tair结合

spring3.1.M1中的cache功能比较简便。可以与Tair结合,这样就不必每次缓存数据库结果集或者hsf结果的时候都写一段同样的代码。

spring3.1.M1中的cache主要使用两个注解标记。

@Cacheable:负责将方法的返回值加入到缓存中

@CacheEvict:负责清除缓存

@Cacheable 支持如下几个参数:

value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name

key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL

condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL

@CacheEvict 支持如下几个参数:

value:缓存位置名称,不能为空,同上

key:缓存的key,默认为空,同上

condition:触发条件,只有满足条件的情况才会清除缓存,默认为空,支持SpEL

allEntries:true表示清除value中的全部缓存,默认为false

例子:

/**
 * TODO 如果没有注释,那么,你懂的
 *
 * @author : mulou.zzy
 *         Time: 下午3:51
 */
@Component("dos")
public class DoSomeThing {


    @Cacheable(value = "default", key="#a")
    public String doa(int a) {

        return (int)( Math.random()* 1000 )+ "";

    }

    @Cacheable(value = "default",condition="#a > 50")
    public String dob(int a) {
        return (int)(Math.random()* 1000 )+ "";
    }
    //清除掉全部缓存
    @CacheEvict(value="default", key = "#a")
    public  void delete(int a) {
        System.out.println("do delete when a  = " + a);
    }

}

实现结合Tair的Cache必须继承Spring的Cache接口

package com;
/**
 * 一个简单的Tair Cache
 *
 * @author : mulou.zzy
 *         Time: 下午3:31
 */
public class TairCache implements Cache {
    Logger log = Logger.getLogger(Cache.class);
    @Resource
    private MultiClusterTairManager tairManager;

    private int nameSpace;

    public void setNameSpace(int nameSpace) {
        this.nameSpace = nameSpace;
    }

    private String name = "default";

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public MultiClusterTairManager getNativeCache() {
        return tairManager;
    }

    @Override
    public TairResult get(Object key) {
        Result<DataEntry> result = tairManager.get(nameSpace, (Serializable) key);
        if (result != null) {
            if (result.isSuccess() && result.getValue() != null) {
                TairResult tr = new TairResult();
                tr.put((Serializable) result.getValue().getValue());
                return tr;
            } else {
                log.warn(result.isSuccess() ? "value为空" : result.getRc().getMessage());
            }
        }
        return null;
    }

    @Override
    public void put(Object key, Object value) {
        if (key != null || value != null) {
            if (key instanceof TairKey) {
                TairKey tairKey = (TairKey) key;
                this.isRcSuccess(this.tairManager.put(nameSpace, tairKey.getKey(), (Serializable) value, tairKey.getVersion(), tairKey.getTime()));
            }
            this.isRcSuccess(this.tairManager.put(nameSpace, (Serializable) key, (Serializable) value));
        }

    }
  //清除缓存
    @Override
    public void evict(Object key) {
        ResultCode rc = this.tairManager.delete(nameSpace, (Serializable) key);
        this.isRcSuccess(rc);
    }
  //tair返回是否成功
    public boolean isRcSuccess(ResultCode rc) {
        if (rc != null) {
            if (rc.isSuccess()) {
                return true;
            } else {
                log.warn(rc.getMessage());
                return false;
            }
        }
        log.warn("获取不到ResultCode");
        return false;
    }
  //本来是清楚所有缓存方法,但是我们这里禁止掉。
    @Override
    public void clear() {
        System.out.println("not allow to clear");
    }
}

因为@Cacheable标记中没有设置缓存时间和version的地方,所以我封装了一个TairKey类,存储Key和Version、time

但是这也不是一个好的解决方案, 目前我在用的是把key设置成String类型,在字符串末尾带上-version-time表示version和time

/**
 * TODO 如果没有注释,那么,你懂的
 *
 * @author : mulou.zzy
 *         Time: 上午11:34
 */
public class TairKey implements Serializable {

    Serializable key;
    int time = 0;
    int version = 0;

    public int getTime() {
        return time;
    }

    public int getVersion() {
        return version;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public Serializable getKey() {
        return key;
    }

    public void setKey(Serializable key) {
        this.key = key;
    }
}

TairResult是封装了Tair返回的类

/**
 * TODO 如果没有注释,那么,你懂的
 *
 * @author : mulou.zzy
 *         Time: 下午3:41
 */
public class TairResult<T extends Serializable> implements Cache.ValueWrapper {
    private T result;

    /**
     *     Tair上的版本号
     *
     */
    private int version;
    /**
     *     存储时间,单位为秒
     */
    private int time;

    @Override
    public Object get() {

        return result;
    }
    public void put(T res){
        this.result = res;
    }
}

最后是配置的xml

<?xml version="1.0" encoding="GBK"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
               http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
     http://www.springframework.org/schema/cache  http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
          http://www.springframework.org/schema/p  http://www.springframework.org/schema/p/spring-p.xsd"
       default-autowire="byName">
    <cache:annotation-driven cache-manager="cacheManager"/>
    <context:annotation-config />
    <context:component-scan base-package="com"/>
    <bean id="tairManager" class="com.taobao.tair.impl.mc.MultiClusterTairManager"
          init-method="init">
        <property name="configID" value="ldbcommon-daily"/>
        <property name="dynamicConfig">
            <value type="java.lang.Boolean">true</value>
        </property>
    </bean>
    <!-- generic cache manager -->
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean class="com.TairCache" p:name="default"/>
            </set>
        </property>
    </bean>

</beans>

然后跑测试类

/**
 * TODO 如果没有注释,那么,你懂的
 *
 * @author : mulou.zzy
 *         Time: 下午3:08
 */
public class Test {
//    org.springframework.cache.ehcache.EhCacheCacheManager   ;
//
//
//    org.springframework.cache.support.SimpleCacheManager   ;
//    ConcurrentCacheFactoryBean   ;
//    ConcurrentMapCache
//}

    public static void  main(String s[]){
        ApplicationContext ac = new ClassPathXmlApplicationContext("T.xml");
        DoSomeThing dos = (DoSomeThing)ac.getBean("dos");
        System.out.println(dos.doa(1111));
        System.out.println(dos.doa(1111));
       dos.delete(1111);
        System.out.println(dos.doa(1111));
        System.out.println(dos.dob(1200));
        System.out.println(dos.dob(1200));
        dos.delete(1200);
        System.out.println(dos.dob(1200));
        System.out.println(dos.dob(11));
        System.out.println(dos.dob(11));
    }
}
原文地址:https://www.cnblogs.com/huamulou/p/2949704.html