欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

利用spring的拦截器自定义缓存的实现实例代码

程序员文章站 2023-08-13 21:12:47
本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示。 memcached 是一个高性能的分布式内存对象缓存系统,用于动态web应用以减轻数据库...

本文研究的主要是利用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);
		}
	}
}

总结

以上就是本文关于利用spring的拦截器自定义缓存的实现实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!