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