本文研究的主要是利用spring的拦截器自定义缓存的实现,具体实现代码如下所示。
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。本文利用Memcached 的实例和spring的拦截器实现缓存自定义的实现。利用拦截器读取自定义的缓存标签,key值的生成策略。
自定义的Cacheable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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
1
2
3
4
5
6
7
8
9
10
11
12
|
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标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//使用拦截到方法的参数生成参数
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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
1
2
3
4
5
6
7
|
//使用生成器生成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信息的帮助类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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;
}
}
|
参数的设置
1
2
3
4
5
|
//使用参数设置key
@Cacheable (namespace= "BlackList" , keyArgs={ 0 , 1 })
public int anotherMethond( int a, int b) {
return 100 ;
}
|
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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的拦截器自定义缓存的实现实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/maoyeqiu/article/details/50325779