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