利用spring的 * 自定义缓存的实现实例代码

作者:txxs 时间:2022-07-22 00:44:47 

本文研究的主要是利用spring的 * 自定义缓存的实现,具体实现代码如下所示。

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。本文利用Memcached 的实例和spring的 * 实现缓存自定义的实现。利用 * 读取自定义的缓存标签,key值的生成策略。

自定义的Cacheable


package com.jeex.sci;
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {
String namespace();
String key() default "";
int[] keyArgs() default {
}
;
String[] keyProperties() default {
}
;
String keyGenerator() default "";
int expires() default 1800;
}

自定义的CacheEvict


package com.jeex.sci;
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheEvict {
String namespace();
String key() default "";
int[] keyArgs() default {
}
;
String[] keyProperties() default {
}
;
String keyGenerator() default "";
}

spring如果需要前后通知的话,一般会实现MethodInterceptor public Object invoke(MethodInvocation invocation) throws Throwable


public Object invoke(MethodInvocation invoction) throws Throwable {
Method method = invoction.getMethod();
Cacheable c = method.getAnnotation(Cacheable.class);
if (c != null) {
return handleCacheable(invoction, method, c);
}
CacheEvict ce = method.getAnnotation(CacheEvict.class);
if (ce != null) {
return handleCacheEvict(invoction, ce);
}
return invoction.proceed();
}

处理cacheable标签


private Object handleCacheable(MethodInvocation invoction, Method method,
   Cacheable c) throws Throwable {
String key = getKey(invoction, KeyInfo.fromCacheable(c));
if (key.equals("")) {
if (log.isDebugEnabled()){
log.warn("Empty cache key, the method is " + method);
}
return invoction.proceed();
}
long nsTag = (long) memcachedGet(c.namespace());
if (nsTag == null) {
nsTag = long.valueOf(System.currentTimeMillis());
memcachedSet(c.namespace(), 24*3600, long.valueOf(nsTag));
}
key = makeMemcachedKey(c.namespace(), nsTag, key);
Object o = null;
o = memcachedGet(key);
if (o != null) {
if (log.isDebugEnabled()) {
log.debug("CACHE HIT: Cache Key = " + key);
}
} else {
if (log.isDebugEnabled()) {
log.debug("CACHE MISS: Cache Key = " + key);
}
o = invoction.proceed();
memcachedSet(key, c.expires(), o);
}
return o;
}

处理cacheEvit标签


private Object handleCacheEvict(MethodInvocation invoction,  
   CacheEvict ce) throws Throwable {
 String key = getKey(invoction, KeyInfo.fromCacheEvict(ce));    

if (key.equals("")) {  
   if (log.isDebugEnabled()) {
     log.debug("Evicting " + ce.namespace());
   }
   memcachedDelete(ce.namespace());
 } else {
   Long nsTag = (Long) memcachedGet(ce.namespace());
   if (nsTag != null) {
     key = makeMemcachedKey(ce.namespace(), nsTag, key);
     if (log.isDebugEnabled()) {
       log.debug("Evicting " + key);
     }
     memcachedDelete(key);        
   }
 }
 return invoction.proceed();
}

根据参数生成key


//使用拦截到方法的参数生成参数
private String getKeyWithArgs(Object[] args, int[] argIndex) {
 StringBuilder key = new StringBuilder();
 boolean first = true;
 for (int index: argIndex) {
   if (index < 0 || index >= args.length) {
     throw new IllegalArgumentException("Index out of bound");
   }
   if (!first) {
     key.append(':');
   } else {
     first = false;
   }
   key = key.append(args[index]);
 }
 return key.toString();
}

根据属性生成key


private String getKeyWithProperties(Object o, String props[])  
   throws Exception {
 StringBuilder key = new StringBuilder();
 boolean first = true;
 for (String prop: props) {
   //把bean的属性转为获取方法的名字
   String methodName = "get"  
       + prop.substring(0, 1).toUpperCase()  
       + prop.substring(1);
   Method m = o.getClass().getMethod(methodName);
   Object r = m.invoke(o, (Object[]) null);
   if (!first) {
     key.append(':');
   } else {
     first = false;
   }
   key = key.append(r);
 }
 return key.toString();
}

利用自定义的生成器生成key


//使用生成器生成key
private String getKeyWithGenerator(MethodInvocation invoction, String keyGenerator)  
   throws Exception {
 Class<?> ckg = Class.forName(keyGenerator);
 CacheKeyGenerator ikg = (CacheKeyGenerator)ckg.newInstance();
 return ikg.generate(invoction.getArguments());
}

保存key信息的帮助类


private static class KeyInfo {
String key;
int[] keyArgs;
String keyProperties[];
String keyGenerator;
static KeyInfo fromCacheable(Cacheable c) {
KeyInfo ki = new KeyInfo();
ki.key = c.key();
ki.keyArgs = c.keyArgs();
ki.keyGenerator = c.keyGenerator();
ki.keyProperties = c.keyProperties();
return ki;
}
static KeyInfo fromCacheEvict(CacheEvict ce) {
KeyInfo ki = new KeyInfo();
ki.key = ce.key();
ki.keyArgs = ce.keyArgs();
ki.keyGenerator = ce.keyGenerator();
ki.keyProperties = ce.keyProperties();
return ki;
}
String key() {
return key;
}
int[] keyArgs() {
return keyArgs;
}
String[] keyProperties() {
return keyProperties;
}
String keyGenerator() {
return keyGenerator;
}
}

参数的设置


//使用参数设置key
@Cacheable(namespace="BlackList", keyArgs={0, 1})
public int anotherMethond(int a, int b) {
 return 100;
}

测试类:


package com.jeex.sci.test;
import net.spy.memcached.MemcachedClient;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class TestMain {
public static void main(String args[]) throws InterruptedException{
ApplicationContext ctx = new FileSystemXmlApplicationContext("/src/test/resources/beans.xml");
MemcachedClient mc = (MemcachedClient) ctx.getBean("memcachedClient");
BlackListDaoImpl dao = (BlackListDaoImpl)ctx.getBean("blackListDaoImpl");
while (true) {
System.out.println("################################GETTING START######################");
mc.flush();
BlackListQuery query = new BlackListQuery(1, "222.231.23.13");
dao.searchBlackListCount(query);
dao.searchBlackListCount2(query);
BlackListQuery query2 = new BlackListQuery(1, "123.231.23.14");
dao.anotherMethond(333, 444);
dao.searchBlackListCount2(query2);
dao.searchBlackListCount3(query2);
dao.evict(query);
dao.searchBlackListCount2(query);
dao.evictAll();
dao.searchBlackListCount3(query2);
Thread.sleep(300);
}
}
}

来源:http://blog.csdn.net/maoyeqiu/article/details/50325779

标签:spring,缓存, ,
0
投稿

猜你喜欢

  • C# DES加密算法中向量的作用详细解析

    2022-07-13 07:49:48
  • Java微信支付之公众号支付、扫码支付实例

    2022-07-10 10:23:11
  • java使用集合实现通讯录功能

    2023-01-30 21:27:15
  • Android 自定义View之边缘凹凸的优惠券效果的开发过程

    2021-12-30 07:25:10
  • Android中Activity启动默认不显示输入法解决方法

    2022-12-27 20:49:30
  • SpringBoot MongoDB 索引冲突分析及解决方法

    2023-01-23 06:28:05
  • 详解Java中List的正确的删除方法

    2021-09-19 13:20:42
  • C#中的Linq To XML讲解

    2021-06-29 18:39:43
  • 处理java异步事件的阻塞和非阻塞方法分析

    2023-04-16 05:06:01
  • java反射获取和调用方法

    2021-11-23 11:05:02
  • 一篇文章带你Java Spring开发入门

    2021-06-25 10:04:15
  • Java实现打印二叉树所有路径的方法

    2021-07-13 15:52:57
  • Android实战教程第八篇之短信备份

    2021-07-17 23:31:43
  • Java实现对两个List快速去重并排序操作示例

    2023-05-02 03:40:14
  • Java中list.contains()的用法及拓展

    2022-11-06 21:04:59
  • 详解kafka中的消息分区分配算法

    2021-06-02 08:16:15
  • springboot之如何获取项目目录路径

    2022-08-09 21:44:17
  • java微信企业号开发之开发模式的开启

    2022-03-20 10:58:02
  • 使用Postman传递arraylist数据给springboot方式

    2022-08-27 01:13:01
  • java数据结构与算法之noDups去除重复项算法示例

    2023-06-19 08:50:34
  • asp之家 软件编程 m.aspxhome.com