利用spring的拦截器自定义缓存的实现实例代码
本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示。
Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。本文利用Memcached的实例和spring的拦截器实现缓存自定义的实现。利用拦截器读取自定义的缓存标签,key值的生成策略。
自定义的Cacheable
packagecom.jeex.sci; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public@interfaceCacheable{ Stringnamespace(); Stringkey()default""; int[]keyArgs()default{ } ; String[]keyProperties()default{ } ; StringkeyGenerator()default""; intexpires()default1800; }
自定义的CacheEvict
packagecom.jeex.sci; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public@interfaceCacheEvict{ Stringnamespace(); Stringkey()default""; int[]keyArgs()default{ } ; String[]keyProperties()default{ } ; StringkeyGenerator()default""; }
spring如果需要前后通知的话,一般会实现MethodInterceptorpublicObjectinvoke(MethodInvocationinvocation)throwsThrowable
publicObjectinvoke(MethodInvocationinvoction)throwsThrowable{ Methodmethod=invoction.getMethod(); Cacheablec=method.getAnnotation(Cacheable.class); if(c!=null){ returnhandleCacheable(invoction,method,c); } CacheEvictce=method.getAnnotation(CacheEvict.class); if(ce!=null){ returnhandleCacheEvict(invoction,ce); } returninvoction.proceed(); }
处理cacheable标签
privateObjecthandleCacheable(MethodInvocationinvoction,Methodmethod, Cacheablec)throwsThrowable{ Stringkey=getKey(invoction,KeyInfo.fromCacheable(c)); if(key.equals("")){ if(log.isDebugEnabled()){ log.warn("Emptycachekey,themethodis"+method); } returninvoction.proceed(); } longnsTag=(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); Objecto=null; o=memcachedGet(key); if(o!=null){ if(log.isDebugEnabled()){ log.debug("CACHEHIT:CacheKey="+key); } }else{ if(log.isDebugEnabled()){ log.debug("CACHEMISS:CacheKey="+key); } o=invoction.proceed(); memcachedSet(key,c.expires(),o); } returno; }
处理cacheEvit标签
privateObjecthandleCacheEvict(MethodInvocationinvoction, CacheEvictce)throwsThrowable{ Stringkey=getKey(invoction,KeyInfo.fromCacheEvict(ce)); if(key.equals("")){ if(log.isDebugEnabled()){ log.debug("Evicting"+ce.namespace()); } memcachedDelete(ce.namespace()); }else{ LongnsTag=(Long)memcachedGet(ce.namespace()); if(nsTag!=null){ key=makeMemcachedKey(ce.namespace(),nsTag,key); if(log.isDebugEnabled()){ log.debug("Evicting"+key); } memcachedDelete(key); } } returninvoction.proceed(); }
根据参数生成key
//使用拦截到方法的参数生成参数 privateStringgetKeyWithArgs(Object[]args,int[]argIndex){ StringBuilderkey=newStringBuilder(); booleanfirst=true; for(intindex:argIndex){ if(index<0||index>=args.length){ thrownewIllegalArgumentException("Indexoutofbound"); } if(!first){ key.append(':'); }else{ first=false; } key=key.append(args[index]); } returnkey.toString(); }
根据属性生成key
privateStringgetKeyWithProperties(Objecto,Stringprops[]) throwsException{ StringBuilderkey=newStringBuilder(); booleanfirst=true; for(Stringprop:props){ //把bean的属性转为获取方法的名字 StringmethodName="get" +prop.substring(0,1).toUpperCase() +prop.substring(1); Methodm=o.getClass().getMethod(methodName); Objectr=m.invoke(o,(Object[])null); if(!first){ key.append(':'); }else{ first=false; } key=key.append(r); } returnkey.toString(); }
利用自定义的生成器生成key
//使用生成器生成key privateStringgetKeyWithGenerator(MethodInvocationinvoction,StringkeyGenerator) throwsException{ Class>ckg=Class.forName(keyGenerator); CacheKeyGeneratorikg=(CacheKeyGenerator)ckg.newInstance(); returnikg.generate(invoction.getArguments()); }
保存key信息的帮助类
privatestaticclassKeyInfo{ Stringkey; int[]keyArgs; StringkeyProperties[]; StringkeyGenerator; staticKeyInfofromCacheable(Cacheablec){ KeyInfoki=newKeyInfo(); ki.key=c.key(); ki.keyArgs=c.keyArgs(); ki.keyGenerator=c.keyGenerator(); ki.keyProperties=c.keyProperties(); returnki; } staticKeyInfofromCacheEvict(CacheEvictce){ KeyInfoki=newKeyInfo(); ki.key=ce.key(); ki.keyArgs=ce.keyArgs(); ki.keyGenerator=ce.keyGenerator(); ki.keyProperties=ce.keyProperties(); returnki; } Stringkey(){ returnkey; } int[]keyArgs(){ returnkeyArgs; } String[]keyProperties(){ returnkeyProperties; } StringkeyGenerator(){ returnkeyGenerator; } }
参数的设置
//使用参数设置key @Cacheable(namespace="BlackList",keyArgs={0,1}) publicintanotherMethond(inta,intb){ return100; }
测试类:
packagecom.jeex.sci.test; importnet.spy.memcached.MemcachedClient; importorg.junit.Test; importorg.springframework.context.ApplicationContext; importorg.springframework.context.support.FileSystemXmlApplicationContext; publicclassTestMain{ publicstaticvoidmain(Stringargs[])throwsInterruptedException{ ApplicationContextctx=newFileSystemXmlApplicationContext("/src/test/resources/beans.xml"); MemcachedClientmc=(MemcachedClient)ctx.getBean("memcachedClient"); BlackListDaoImpldao=(BlackListDaoImpl)ctx.getBean("blackListDaoImpl"); while(true){ System.out.println("################################GETTINGSTART######################"); mc.flush(); BlackListQueryquery=newBlackListQuery(1,"222.231.23.13"); dao.searchBlackListCount(query); dao.searchBlackListCount2(query); BlackListQueryquery2=newBlackListQuery(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的拦截器自定义缓存的实现实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!