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;
}
}