package com.jarvis.cache; import java.lang.reflect.Method; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jarvis.cache.annotation.Cache; import com.jarvis.cache.annotation.CacheDelete; import com.jarvis.cache.annotation.CacheDeleteKey; import com.jarvis.cache.annotation.CacheDeleteTransactional; import com.jarvis.cache.annotation.ExCache; import com.jarvis.cache.aop.CacheAopProxyChain; import com.jarvis.cache.aop.DeleteCacheAopProxyChain; import com.jarvis.cache.clone.ICloner; import com.jarvis.cache.lock.ILock; import com.jarvis.cache.script.AbstractScriptParser; import com.jarvis.cache.serializer.ISerializer; import com.jarvis.cache.to.AutoLoadConfig; import com.jarvis.cache.to.AutoLoadTO; import com.jarvis.cache.to.CacheConfigTO; import com.jarvis.cache.to.CacheKeyTO; import com.jarvis.cache.to.CacheWrapper; import com.jarvis.cache.to.ProcessingTO; import com.jarvis.cache.type.CacheOpType; /** * 缓存管理抽象类 * @author jiayu.qiu */ public abstract class AbstractCacheManager implements ICacheManager { private static final Logger logger=LoggerFactory.getLogger(AbstractCacheManager.class); // 解决java.lang.NoSuchMethodError:java.util.Map.putIfAbsent public final ConcurrentHashMap<CacheKeyTO, ProcessingTO> processing=new ConcurrentHashMap<CacheKeyTO, ProcessingTO>(); private final AutoLoadHandler autoLoadHandler; private String namespace; /** * 加载数据重试次数,默认值为1: */ private int loadDataTryCnt=1; /** * 序列化工具,默认使用Hessian2 */ private final ISerializer<Object> serializer; /** * 表达式解析器 */ private final AbstractScriptParser scriptParser; private final RefreshHandler refreshHandler; private ICloner cloner; /** * 分布式锁 */ private ILock lock; public AbstractCacheManager(AutoLoadConfig config, ISerializer<Object> serializer, AbstractScriptParser scriptParser) { autoLoadHandler=new AutoLoadHandler(this, config); this.serializer=serializer; this.cloner=this.serializer; this.scriptParser=scriptParser; registerFunction(config.getFunctions()); refreshHandler=new RefreshHandler(this, config); } private Object writeOnly(CacheAopProxyChain pjp, Cache cache) throws Throwable { DataLoaderFactory factory=DataLoaderFactory.getInstance(); DataLoader dataLoader=factory.getDataLoader(); CacheWrapper<Object> cacheWrapper=dataLoader.init(pjp, cache, this).getData().getCacheWrapper(); Object result=cacheWrapper.getCacheObject(); Object[] arguments=pjp.getArgs(); if(scriptParser.isCacheable(cache, arguments, result)) { CacheKeyTO cacheKey=getCacheKey(pjp, cache, result); AutoLoadTO autoLoadTO=autoLoadHandler.getAutoLoadTO(cacheKey);// 注意:这里只能获取AutoloadTO,不能生成AutoloadTO try { writeCache(pjp, pjp.getArgs(), cache, cacheKey, cacheWrapper); if(null != autoLoadTO) { autoLoadTO.setLastLoadTime(cacheWrapper.getLastLoadTime())// 同步加载时间 .setExpire(cacheWrapper.getExpire());// 同步过期时间 } } catch(Exception ex) { logger.error(ex.getMessage(), ex); } } return result; } /** * 处理@Cache 拦截 * @param pjp 切面 * @param cache 注解 * @return T 返回值 * @throws Exception 异常 */ public Object proceed(CacheAopProxyChain pjp, Cache cache) throws Throwable { logger.debug("AbstractCacheManager.proceed"); if(null != cache.opType() && cache.opType() == CacheOpType.WRITE) {// 更新缓存操作 return writeOnly(pjp, cache); } CacheConfigTO config=CacheHelper.getLocalConfig(); if(config != null) { CacheHelper.clearLocalConfig(); if(!config.isCacheAble()) { return getData(pjp); } } Object[] arguments=pjp.getArgs(); if(!scriptParser.isCacheable(cache, arguments)) {// 如果不进行缓存,则直接返回数据 return getData(pjp); } CacheKeyTO cacheKey=getCacheKey(pjp, cache); if(null == cacheKey) { return getData(pjp); } Method method=pjp.getMethod(); // Type returnType=method.getGenericReturnType(); CacheWrapper<Object> cacheWrapper=null; try { cacheWrapper=this.get(cacheKey, method, arguments);// 从缓存中获取数据 } catch(Exception ex) { logger.error(ex.getMessage(), ex); } if(null != cache.opType() && cache.opType() == CacheOpType.READ_ONLY) {// 如果是只读,则直接返回 return null == cacheWrapper ? null : cacheWrapper.getCacheObject(); } if(null != cacheWrapper && !cacheWrapper.isExpired()) { AutoLoadTO autoLoadTO=autoLoadHandler.putIfAbsent(cacheKey, pjp, cache, cacheWrapper); if(null != autoLoadTO) {// 同步最后加载时间 autoLoadTO.setLastRequestTime(System.currentTimeMillis())// .setLastLoadTime(cacheWrapper.getLastLoadTime())// 同步加载时间 .setExpire(cacheWrapper.getExpire());// 同步过期时间 } else {// 如果缓存快要失效,则自动刷新 refreshHandler.doRefresh(pjp, cache, cacheKey, cacheWrapper); } return cacheWrapper.getCacheObject(); } DataLoaderFactory factory=DataLoaderFactory.getInstance(); DataLoader dataLoader=factory.getDataLoader(); CacheWrapper<Object> newCacheWrapper=null; long loadDataUseTime=0; boolean isFirst; try { newCacheWrapper=dataLoader.init(pjp, cacheKey, cache, this).loadData().getCacheWrapper(); isFirst=dataLoader.isFirst(); loadDataUseTime=dataLoader.getLoadDataUseTime(); } catch(Throwable e) { throw e; } finally { factory.returnObject(dataLoader); } AutoLoadTO autoLoadTO=null; if(isFirst) { autoLoadTO=autoLoadHandler.putIfAbsent(cacheKey, pjp, cache, newCacheWrapper); try { writeCache(pjp, pjp.getArgs(), cache, cacheKey, newCacheWrapper); if(null != autoLoadTO) {// 同步最后加载时间 autoLoadTO.setLastRequestTime(System.currentTimeMillis())// .setLastLoadTime(newCacheWrapper.getLastLoadTime())// 同步加载时间 .setExpire(newCacheWrapper.getExpire())// 同步过期时间 .addUseTotalTime(loadDataUseTime);// 统计用时 } } catch(Exception ex) { logger.error(ex.getMessage(), ex); } } return newCacheWrapper.getCacheObject(); } /** * 处理@CacheDelete 拦截 * @param jp 切点 * @param cacheDelete 拦截到的注解 * @param retVal 返回值 */ public void deleteCache(DeleteCacheAopProxyChain jp, CacheDelete cacheDelete, Object retVal) { Object[] arguments=jp.getArgs(); CacheDeleteKey[] keys=cacheDelete.value(); if(null == keys || keys.length == 0) { return; } String className=jp.getTargetClass().getName(); String methodName=jp.getMethod().getName(); for(int i=0; i < keys.length; i++) { CacheDeleteKey keyConfig=keys[i]; try { String _keys[]=keyConfig.value(); String _hfield=keyConfig.hfield(); if(!scriptParser.isCanDelete(keyConfig, arguments, retVal)) { continue; } for(String _key: _keys) { CacheKeyTO key=getCacheKey(className, methodName, arguments, _key, _hfield, retVal, true); if(null != key && !CacheHelper.addDeleteCacheKey(key)) { this.delete(key); } } } catch(Exception e) { logger.error(e.getMessage(), e); } } } /** * 用于处理事务下,事务处理完后才删除缓存,避免因事务失败造成缓存中的数据不一致问题。 * @param pjp * @param cacheDeleteTransactional * @return * @throws Throwable */ public Object proceedDeleteCacheTransactional(CacheAopProxyChain pjp, CacheDeleteTransactional cacheDeleteTransactional) throws Throwable { Object[] arguments=pjp.getArgs(); Object result=null; Set<CacheKeyTO> set0=CacheHelper.getDeleteCacheKeysSet(); boolean isStart=null == set0; try { CacheHelper.initDeleteCacheKeysSet();// 初始化Set result=pjp.doProxyChain(arguments); } catch(Throwable e) { throw e; } finally { } Set<CacheKeyTO> set=CacheHelper.getDeleteCacheKeysSet(); if(isStart) { if(null != set && set.size() > 0) { try { for(CacheKeyTO key: set) { this.delete(key); logger.debug("proceedDeleteCacheTransactional delete-->" + key); } } catch(Throwable e) { logger.error(e.getMessage(), e); } } CacheHelper.clearDeleteCacheKeysSet(); } return result; } /** * 直接加载数据(加载后的数据不往缓存放) * @param pjp CacheAopProxyChain * @return Object * @throws Throwable */ private Object getData(CacheAopProxyChain pjp) throws Throwable { try { long startTime=System.currentTimeMillis(); Object[] arguments=pjp.getArgs(); Object result=pjp.doProxyChain(arguments); long useTime=System.currentTimeMillis() - startTime; AutoLoadConfig config=autoLoadHandler.getConfig(); if(config.isPrintSlowLog() && useTime >= config.getSlowLoadTime()) { String className=pjp.getTargetClass().getName(); logger.error(className + "." + pjp.getMethod().getName() + ", use time:" + useTime + "ms"); } return result; } catch(Throwable e) { throw e; } } public void writeCache(CacheAopProxyChain pjp, Object[] arguments, Cache cache, CacheKeyTO cacheKey, CacheWrapper<Object> cacheWrapper) throws Exception { if(null == cacheKey) { return; } Method method=pjp.getMethod(); if(cacheWrapper.getExpire() >= 0) { this.setCache(cacheKey, cacheWrapper, method, arguments); } ExCache[] exCaches=cache.exCache(); if(null == exCaches || exCaches.length == 0) { return; } Object result=cacheWrapper.getCacheObject(); for(ExCache exCache: exCaches) { try { if(!scriptParser.isCacheable(exCache, arguments, result)) { continue; } CacheKeyTO exCacheKey=getCacheKey(pjp, arguments, exCache, result); if(null == exCacheKey) { continue; } Object exResult=null; if(null == exCache.cacheObject() || exCache.cacheObject().length() == 0) { exResult=result; } else { exResult=scriptParser.getElValue(exCache.cacheObject(), arguments, result, true, Object.class); } int exCacheExpire=scriptParser.getRealExpire(exCache.expire(), exCache.expireExpression(), arguments, exResult); CacheWrapper<Object> exCacheWrapper=new CacheWrapper<Object>(exResult, exCacheExpire); AutoLoadTO tmpAutoLoadTO=this.autoLoadHandler.getAutoLoadTO(exCacheKey); if(exCacheExpire >= 0) { this.setCache(exCacheKey, exCacheWrapper, method, arguments); if(null != tmpAutoLoadTO) { tmpAutoLoadTO.setExpire(exCacheExpire)// .setLastLoadTime(exCacheWrapper.getLastLoadTime());// } } } catch(Exception ex) { logger.error(ex.getMessage(), ex); } } } public void destroy() { autoLoadHandler.shutdown(); refreshHandler.shutdown(); logger.info("cache destroy ... ... ..."); } /** * 生成缓存KeyTO * @param className 类名 * @param methodName 方法名 * @param arguments 参数 * @param _key key * @param _hfield hfield * @param result 执行实际方法的返回值 * @return CacheKeyTO */ private CacheKeyTO getCacheKey(String className, String methodName, Object[] arguments, String _key, String _hfield, Object result, boolean hasRetVal) { String key=null; String hfield=null; if(null != _key && _key.trim().length() > 0) { try { key=scriptParser.getDefinedCacheKey(_key, arguments, result, hasRetVal); if(null != _hfield && _hfield.trim().length() > 0) { hfield=scriptParser.getDefinedCacheKey(_hfield, arguments, result, hasRetVal); } } catch(Exception ex) { logger.error(ex.getMessage(), ex); } } else { key=CacheUtil.getDefaultCacheKey(className, methodName, arguments); } if(null == key || key.trim().length() == 0) { logger.error(className + "." + methodName + "; cache key is empty"); return null; } return new CacheKeyTO(namespace, key, hfield); } /** * 生成缓存 Key * @param pjp * @param cache * @return String 缓存Key */ private CacheKeyTO getCacheKey(CacheAopProxyChain pjp, Cache cache) { String className=pjp.getTargetClass().getName(); String methodName=pjp.getMethod().getName(); Object[] arguments=pjp.getArgs(); String _key=cache.key(); String _hfield=cache.hfield(); return getCacheKey(className, methodName, arguments, _key, _hfield, null, false); } /** * 生成缓存 Key * @param pjp * @param cache * @param result 执行结果值 * @return 缓存Key */ private CacheKeyTO getCacheKey(CacheAopProxyChain pjp, Cache cache, Object result) { String className=pjp.getTargetClass().getName(); String methodName=pjp.getMethod().getName(); Object[] arguments=pjp.getArgs(); String _key=cache.key(); String _hfield=cache.hfield(); return getCacheKey(className, methodName, arguments, _key, _hfield, result, true); } /** * 生成缓存 Key * @param pjp * @param arguments * @param exCache * @param result 执行结果值 * @return 缓存Key */ private CacheKeyTO getCacheKey(CacheAopProxyChain pjp, Object[] arguments, ExCache exCache, Object result) { String className=pjp.getTargetClass().getName(); String methodName=pjp.getMethod().getName(); String _key=exCache.key(); if(null == _key || _key.trim().length() == 0) { return null; } String _hfield=exCache.hfield(); return getCacheKey(className, methodName, arguments, _key, _hfield, result, true); } public ISerializer<Object> getSerializer() { return serializer; } public AutoLoadHandler getAutoLoadHandler() { return this.autoLoadHandler; } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace=namespace; } public int getLoadDataTryCnt() { return loadDataTryCnt; } public void setLoadDataTryCnt(int loadDataTryCnt) { if(loadDataTryCnt >= 0 && loadDataTryCnt < 5) { this.loadDataTryCnt=loadDataTryCnt; } } public AbstractScriptParser getScriptParser() { return scriptParser; } public ICloner getCloner() { return cloner; } public void setCloner(ICloner cloner) { this.cloner=cloner; } private void registerFunction(Map<String, String> funcs) { if(null == scriptParser) { return; } if(null == funcs || funcs.isEmpty()) { return; } Iterator<Map.Entry<String, String>> it=funcs.entrySet().iterator(); while(it.hasNext()) { Map.Entry<String, String> entry=it.next(); try { String name=entry.getKey(); Class<?> cls=Class.forName(entry.getValue()); Method method=cls.getDeclaredMethod(name, new Class[]{Object.class}); scriptParser.addFunction(name, method); } catch(Exception e) { logger.error(e.getMessage(), e); } } } public ILock getLock() { return lock; } public void setLock(ILock lock) { this.lock=lock; } }