Package com.skyline.energy.executor.impl

Source Code of com.skyline.energy.executor.impl.CacheExecutor

package com.skyline.energy.executor.impl;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.skyline.energy.cache.Cache;
import com.skyline.energy.cache.CacheManager;
import com.skyline.energy.cache.CacheObject;
import com.skyline.energy.cache.CacheResult;
import com.skyline.energy.definition.CacheDefinition;
import com.skyline.energy.definition.CacheDefinitionCollection;
import com.skyline.energy.definition.CacheDeleteDefinition;
import com.skyline.energy.definition.VersionUpdateDefinition;
import com.skyline.energy.exception.CacheUnreachableException;
import com.skyline.energy.exception.DaoGenerateException;
import com.skyline.energy.executor.DataAccessExecutor;
import com.skyline.energy.utils.CommonUtils;
import com.skyline.energy.utils.Page;

public class CacheExecutor implements DataAccessExecutor {
  private static final Log LOGGER = LogFactory.getLog(CacheExecutor.class);
  private CacheDefinitionCollection cacheDefinitionCollection;
  private final CacheManager cacheManager;
  private DataAccessExecutor dataAccessExecutor;

  public CacheExecutor(CacheManager cacheManager, Method method) throws DaoGenerateException {
    this.cacheManager = cacheManager;
    this.cacheDefinitionCollection = new CacheDefinitionCollection(method);
  }

  public void setDataAccessExecutor(DataAccessExecutor dataAccessExecutor) {
    this.dataAccessExecutor = dataAccessExecutor;
  }

  @Override
  public Object execute(Object obj, Object[] args) {
    if (!cacheDefinitionCollection.needCacheOpration()) {
      return dataAccessExecutor.execute(obj, args);
    }

    try {
      CacheResult cacheResult = beforeDataAccess(args);

      Object retVal = dataAccessExecutor.execute(obj, args);
      cacheResult.setRetVal(retVal);
     
      afterDataAccess(cacheResult, args);
     
      return retVal;
    } catch (CacheUnreachableException e) {
      return dataAccessExecutor.execute(obj, args);
    }
   
  }

  private CacheResult beforeDataAccess(Object[] args) throws CacheUnreachableException {
    CacheResult cacheResult = new CacheResult(false);

    CacheDefinition cacheDefinition = cacheDefinitionCollection.getCacheDefinition();

    if (cacheDefinition == null) {
      return cacheResult;
    }

    String key = cacheDefinition.generateCacheKey(args);
    if (StringUtils.isEmpty(key)) {
      LOGGER.debug("创建缓存KEY失败,不进行缓存!");
      return cacheResult;
    }
    cacheResult.setKey(key);

    Cache cache = cacheManager.getCache(cacheDefinition.getPool());
    cacheResult.setCache(cache);

    CacheObject oldItem = (CacheObject) cache.get(key);
    LOGGER.debug("从" + key + "获取缓存对象:" + oldItem);
    if (oldItem != null) {
      return compareVersionKey(cacheDefinition, cacheResult, oldItem, args);
    }

    return cacheResult;
  }

  private CacheResult compareVersionKey(CacheDefinition cacheDefinition, CacheResult cacheResult,
      CacheObject oldItem, Object[] args) {
    long itemVersion = oldItem.getVersion();
    Object cachedItem = oldItem.getCacheObject();

    Object[] params;
    boolean isReturnCollection = cacheDefinition.isReturnCollection();
    if (isReturnCollection) {
      params = args;
    } else {// 单个对象
      // 缓存对象为空或者不需要判断versionKey就作为命中处理
      if (cachedItem == null || StringUtils.isEmpty(cacheDefinition.getVkey())) {
        return processCacheHit(cacheResult, cachedItem, args);
      }

      params = new Object[] { cachedItem };
    }

    String versionKey = cacheDefinition.generateVersionKey(params);
    if (StringUtils.isEmpty(versionKey)) {
      LOGGER.debug("无法生成更新版本信息的缓存KEY,获取缓存失败");
      return cacheResult;
    }
    LOGGER.debug("生成版本信息的缓存KEY:" + versionKey);
    cacheResult.setVersionKey(versionKey);

    Cache cache = cacheResult.getCache();

    long currentVersion = getCurrentVersion(cache, versionKey);
    cacheResult.setCurrentVersion(currentVersion);

    if (currentVersion != 0 && currentVersion == itemVersion) { // 版本一致则表示有效
      return processCacheHit(cacheResult, cachedItem, args);
    } else {
      LOGGER.debug("当前版本为:" + currentVersion + ",缓存对象版本号为:" + itemVersion + ",Cache没有命中,直接调用DAO方法");
      return cacheResult;
    }
  }

  private long getCurrentVersion(Cache cache, String versionKey) {
    Long cachedVersion = (Long) cache.get(versionKey);
    LOGGER.debug("从" + versionKey + "获取版本缓存对象:" + cachedVersion);
    long currentVersion = 0;
    if (cachedVersion != null) {
      currentVersion = cachedVersion;
    }
    return currentVersion;
  }

  private CacheResult processCacheHit(CacheResult cacheResult, Object cachedItem, Object[] args) {
    LOGGER.debug("版本号一致,缓存命中");

    String key = cacheResult.getKey();
    cacheResult.setRetVal(cachedItem);

    CacheDefinition cacheDefinition = cacheDefinitionCollection.getCacheDefinition();
    Cache cache = cacheResult.getCache();

    if (cacheDefinition.isReturnCollection()) {
      Page page = CommonUtils.getPageArgument(args, cacheDefinition.getPageIndex());
      if (page != null) { // 判断分页参数是非被复用
        String pageKey = cacheDefinition.generatePageKey(args, key);
        LOGGER.debug("缓存为需要分页的缓存,页码(" + page.getCurpage() + "),对应的分页缓存KEY为:" + pageKey);
        Page cachePage = (Page) cache.get(pageKey);
        page.setTotal(cachePage.getTotal());
        cacheResult.setPageKey(pageKey);
      }
    }
    cacheResult.setHit(true);
    return cacheResult;
  }

  private void afterDataAccess(CacheResult cacheResult, Object[] args) throws CacheUnreachableException {
    CacheDefinition cacheDefinition = cacheDefinitionCollection.getCacheDefinition();
    if (cacheDefinition == null) {
      updateVersion(cacheResult, args);
      deleteCache(cacheResult, args);
      return;
    }

    String key = cacheResult.getKey();
    Object exeResult = cacheResult.getRetVal();
    Cache cache = cacheResult.getCache();

    cacheResult = recacheVersionKey(cacheResult, args, cacheDefinition);

    long expire = cacheDefinition.getExpire();

    long currentVersion = cacheResult.getCurrentVersion();

    CacheObject newItem = new CacheObject((Serializable) exeResult, currentVersion);
    cache.add(key, newItem, expire);
    LOGGER.debug("缓存对象到:" + key + ",缓存时间:" + expire + "毫秒");

    if (cacheDefinition.isReturnCollection()) {
      int pageIndex = cacheDefinition.getPageIndex();
      Page page = CommonUtils.getPageArgument(args, pageIndex);
      if (page != null) {
        String pageKey = cacheResult.getPageKey();
        if (pageKey == null) {
          pageKey = cacheDefinition.generatePageKey(args, key);
        }
        if (!StringUtils.isEmpty(pageKey)) {
          cache.add(pageKey, page, expire);
          LOGGER.debug("缓存为需要分页的缓存,页码(" + page.getCurpage() + "),缓存分页对象到:" + pageKey + ", 缓存时间:" + expire + "毫秒");
        }
      }
    }

  }

  private void updateVersion(CacheResult cacheResult, Object[] args) throws CacheUnreachableException {
    List<VersionUpdateDefinition> updates = cacheDefinitionCollection.getVersionUpdateDefinitions();
    if (updates == null) {
      return;
    }

    for (VersionUpdateDefinition definition : updates) {
      String versionKey = definition.generateVersionKey(args);
      if (versionKey == null) {
        LOGGER.info("无法生成更新版本信息的缓存KEY,更新缓存版本失败");
      }
      long currentVersion = System.currentTimeMillis(); // 改用系统时间作为版本号,防止重构后的版本号与对象的版本正好一致,而是对象无法失效
      if (versionKey != null) {
        Cache cache = cacheManager.getCache(definition.getPool());
        long expire = definition.getExpire();
        cache.add(versionKey, currentVersion, expire);
        LOGGER.debug("更新版本信息的缓存KEY:" + versionKey + "到版本" + currentVersion + ", 缓存时间:" + expire + "毫秒");
      }
    }
  }

  private void deleteCache(CacheResult cacheResult, Object[] args) throws CacheUnreachableException {
    List<CacheDeleteDefinition> deletes = cacheDefinitionCollection.getCacheDeleteDefinitions();
    if (deletes == null) {
      return;
    }

    for (CacheDeleteDefinition definition : deletes) {
      String key = definition.generateCacheKey(args);
      Cache cache = cacheManager.getCache(definition.getPool());
      cache.delete(key);
      LOGGER.debug("删除缓存KEY:" + key);
    }
  }

  private CacheResult recacheVersionKey(CacheResult cacheResult, Object[] args, CacheDefinition cacheDefinition) {
    long currentVersion = cacheResult.getCurrentVersion();
    String versionKey = cacheResult.getVersionKey();
    boolean isReturnCollection = cacheDefinition.isReturnCollection();
    Cache cache = cacheResult.getCache();
    Object result = cacheResult.getRetVal();

    if (currentVersion == 0) { // 原来的version已经因为时间等原因过期,需要重新缓存
      Long cachedCurrentVersion = null;
      // 第一次查询缓存,需要生产版本的key;
      if (versionKey == null) {
        if (isReturnCollection) {
          versionKey = cacheDefinition.generateVersionKey(args);
        } else if (result != null && StringUtils.isNotEmpty(cacheDefinition.getVkey())) {
          versionKey = cacheDefinition.generateVersionKey(new Object[] { result });
        } else {
          LOGGER.info("不需要缓存版本信息");
          return cacheResult;
        }

        if (versionKey == null) {
          LOGGER.info("无法生成更新版本信息的缓存KEY,缓存失败");
          return cacheResult;
        }
        LOGGER.debug("第一次查询缓存,需要生成版本信息的缓存KEY:" + versionKey);
        cachedCurrentVersion = (Long) cache.get(versionKey); // 由于第一次查询无法得知版本信息,所以在知道版本key后才需要再查一次版本信息

      }

      // 为空或者无意义才表明版本信息也需要缓存,否则版本信息就为缓存的版本信息
      if (versionKey != null && (cachedCurrentVersion == null || cachedCurrentVersion <= 0)) {
        currentVersion = System.currentTimeMillis(); // 改用系统时间作为版本号,防止重构后的版本号与对象的版本正好一致,而是对象无法失效
        long expire = cacheDefinition.getExpire();
        cache.add(versionKey, currentVersion, expire);
        LOGGER.debug("更新版本信息的缓存KEY:" + versionKey + "到版本" + currentVersion + ", 缓存时间:" + expire + "毫秒");
        cacheResult.setCurrentVersion(currentVersion);
      } else {
        if (cachedCurrentVersion == null || cachedCurrentVersion <= 0) {
          cachedCurrentVersion = System.currentTimeMillis(); // 改用系统时间作为版本号,防止重构后的版本号与对象的版本正好一致,而是对象无法失效
        }
        cacheResult.setCurrentVersion(cachedCurrentVersion);
      }
    }

    return cacheResult;
  }
}
TOP

Related Classes of com.skyline.energy.executor.impl.CacheExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.