首页 > 编程 > Java > 正文

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

2019-11-26 10:20:02
字体:
来源:转载
供稿:网友

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表