spring AOPと注釈を利用して実現する方法の中でcacheを調べます.私達は一体どれぐらいのシリーズを歩くことができますか?

12545 ワード

テーマ:このコードは開発中によくあるコードです.データベースのあるメインテーブルのデータを調べます.性能を高めるためにキャッシュをします.呼出するたびにキャッシュデータを取ってください.
public Merchant loadCachedMerchant(String merchantId) {
    String key = this.createCacheKey(merchantId);
    Merchant merchant = (Merchant) this.memCachedClient.get(key);//     
    if (merchant == null) {
        merchant = this.merchantDao.searchMerchantByMerchantId1(merchantId);//     
        if (merchant != null) {
            merchant = extraCacheMerchant(merchant);
            this.memCachedClient.put(key, merchant, 5 * 60);
        }
    }

    return merchant;
}
しかし、一般的にはプロジェクトの初期または発展の過程で、どのような業務がキャッシュされているのかよく計画できません.これはキャッシュ再データベースのロジックで共通していることを発見しました.
構想の下で、私達は注釈を利用して、このキャッシュロジックが必要な方法に対して単独で注釈を提供することができると考えられます.このようにして、私達はこれらの切断面を見つけられます.つまり、この特定の注釈の方法があります.例えば、@ServiceCacheといいます.
この@ServiceCacheの注釈に必要なパラメータはキャッシュキーの構成方式と有効時間があります.
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceCache {
    int value() default -1;

    int expire() default 60;

    ServiceCache.Key key() default ServiceCache.Key.JSON;

    String[] includeKeys() default {};

    boolean sync() default false;

    boolean nullPattern() default true;

    public static enum Key {
        JSON,
        TO_STRING;

        private Key() {
        }
    }
}
ここでは、同期実行を制御するためにsyncパラメータを追加しましたが、この同期のパラメータはどのような問題を解決するために使用されますか?ここでキャッシュを使う方法はデータベースへの頻繁な呼び出しの問題を解決するためであり、これらの同時呼び出しはデータベースの圧力を引き起こす可能性があるということが分かります.それでは、私達のロジックでは、キャッシュを先にチェックし、ない場合はデータベースを探しに行きます.この判断ロジックチェックのキャッシュが同時にないことが分かりました.つまり、データベースのデータはキャッシュに入れられていません.この時、これらを同時にデータベースに探しに行きます.
@Aspect
public class ServiceCacheAnnotationAspect {
    private static Logger log = LoggerFactory.getLogger(ServiceCacheAnnotationAspect.class);
    private ICache serviceCache;
    private Object syncLock = new Object();

    public ServiceCacheAnnotationAspect() {
    }
/**
 *      class   @Service   @Repository            @ServiceCache
 **/
    @Around("(@within(org.springframework.stereotype.Service)||
    @within(org.springframework.stereotype.Repository))&&
    @annotation(com.xiaoka.freework.cache.annotation.ServiceCache)") private Object cacheProcess(ProceedingJoinPoint jp) throws Throwable { Class targetClz = jp.getTarget().getClass(); String methodName = jp.getSignature().getName(); if(!(jp.getSignature() instanceof MethodSignature)) { log.warn(" : {}", jp.getSignature().toLongString()); return jp.proceed(); } else { MethodSignature methodSign = (MethodSignature)jp.getSignature(); ServiceCache sc = ServiceCacheUtils.single().findServiceCache(targetClz, methodSign.getMethod()); if(sc == null) { return jp.proceed(); } else { int expire = sc.value() >= 0?sc.value():sc.expire();// if(expire > 0) { String cacheKey = ServiceCacheUtils.single().buildCacheKey(sc, targetClz, methodName, jp.getArgs()); Object rval = null; if(sc.sync()) { Object var9 = this.syncLock; synchronized(this.syncLock) {// rval = this.cacheInvoke(sc, jp, cacheKey, expire);// } } else { rval = this.cacheInvoke(sc, jp, cacheKey, expire); } return rval instanceof ServiceCacheAnnotationAspect.Blank?null:rval; } else { return jp.proceed(); } } } } private Object cacheInvoke(ServiceCache sc, ProceedingJoinPoint jp, String cacheKey, int expire) throws Throwable { log.debug("Load from cache for key : {}", cacheKey); Object rval = this.serviceCache.get(cacheKey); if(rval == null) {// , , log.info("Miss from cache, load backend for key : {}", cacheKey); rval = jp.proceed();// rval = rval == null && sc.nullPattern()?ServiceCacheAnnotationAspect.Blank.INST:rval; if(rval != null) { this.serviceCache.put(cacheKey, rval, expire); } } return rval; } public void setServiceCache(ICache serviceCache) { this.serviceCache = serviceCache; ServiceCacheUtils.single().setCache(serviceCache); } private static class Blank implements Serializable { private static final long serialVersionUID = 3203712628835590212L; private static final ServiceCacheAnnotationAspect.Blank INST = new ServiceCacheAnnotationAspect.Blank(); private Blank() { } } }
実際の使用例はこうです.
@ServiceCache(expire = 600, includeKeys = { "name" })
    public CarProvinceEntity selectProvinceByName(String name) {
        return commonDao.mapper(CarProvinceEntity.class).source(Source.SLAVE)
                        .sql("selectByName").session().selectOne(name);
    }
これは開発業務の人にとって便利です.aopを通じて注釈を結合して、プロジェクトの中でいくつかのうどんを作ることができます.もう多くのプロジェクトの下のフレームワークの一部になりました.
関連知識点リンク:
http://www.cnblogs.com/killbug/p/5271291.html
http://samter.iteye.com/blog/410618http://itindex.net/detail/29812を選択します.aophttp://www.ibm.com/developerworks/cn/java/j-lo-aopi18n/index.html