本文研究的主要是利用spring的攔截器自定義緩存的實現,具體實現代碼如下所示。
Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。本文利用Memcached 的實例和spring的攔截器實現緩存自定義的實現。利用攔截器讀取自定義的緩存標籤,key值的生成策略。
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;} 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 "";} 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();}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;}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(); } //使用攔截到方法的參數生成參數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(); } 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 private String getKeyWithGenerator(MethodInvocation invoction, String keyGenerator) throws Exception { Class<?> ckg = Class.forName(keyGenerator); CacheKeyGenerator ikg = (CacheKeyGenerator)ckg.newInstance(); return ikg.generate(invoction.getArguments()); }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的攔截器自定義緩存的實現實例代碼的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!