springのスクリーンセーバーを利用してユーザー定義のキャッシュを実現する例示的なコード


本研究の主な目的は、springのスクリーンセーバを利用したカスタムキャッシュの実現であり、具体的な実現コードは以下の通りである。
Memcachedは、データベース負荷を軽減するための動的Webアプリケーションのための高性能分散メモリオブジェクトキャッシュシステムである。データとオブジェクトをメモリにキャッシュすることにより、データベースの読み込み回数を減らし、動的、データベースドライバのウェブサイトの速度を向上させる。本明細書では、Memcachedの例とspringのブロッキングを用いて、キャッシュカスタムの実装を実現する。スクリーンセーバを利用して、ユーザー定義のキャッシュラベル、key値の生成ポリシーを読み取ります。
カスタムCachebale

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

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を実現します。

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();
}
cachebaleラベルを処理する

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;
}
cacheEnitラベルの処理

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を生成

//               
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を生成する

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を生成する

//       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情報を保存するヘルプクラス

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のスクリーンセーバーを利用して、ユーザー定義のキャッシュを実現する例示的なコードのすべての内容について、ご協力をお願いします。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。