packageatest.hiyaCache;importjava.lang.reflect.Method;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Hashtable;import org.apache.commons.logging.Log; //commons-loggings-1.1.1.jar
importorg.apache.commons.logging.LogFactory;public classCacheOperation {private static final Log log = LogFactory.getLog(CacheOperation.class);private static CacheOperation singleton = null;private Hashtable cacheMap;//存放缓存数据
private ArrayList threadKeys;//处于线程更新中的key值列表
public staticCacheOperation getInstance() {if (singleton == null) {
singleton= newCacheOperation();
}returnsingleton;
}privateCacheOperation() {
cacheMap= newHashtable();
threadKeys= newArrayList();
}/*** 添加数据缓存
* 与方法getCacheData(String key, long intervalTime, int maxVisitCount)配合使用
*@paramkey
*@paramdata*/
public voidaddCacheData(String key, Object data) {
addCacheData(key, data,true);
}private void addCacheData(String key, Object data, booleancheck) {if (Runtime.getRuntime().freeMemory() < 5L*1024L*1024L) {//虚拟机内存小于10兆,则清除缓存
log.warn("WEB缓存:内存不足,开始清空缓存!");
removeAllCacheData();return;
}else if(check &&cacheMap.containsKey(key)) {
log.warn("WEB缓存:key值= " + key + " 在缓存中重复, 本次不缓存!");return;
}
cacheMap.put(key,newCacheData(data));
}/*** 取得缓存中的数据
* 与方法addCacheData(String key, Object data)配合使用
*@paramkey
*@paramintervalTime 缓存的时间周期,小于等于0时不限制
*@parammaxVisitCount 访问累积次数,小于等于0时不限制
*@return
*/
public Object getCacheData(String key, long intervalTime, intmaxVisitCount) {
CacheData cacheData=(CacheData)cacheMap.get(key);if (cacheData == null) {return null;
}if (intervalTime > 0 && (System.currentTimeMillis() - cacheData.getTime()) >intervalTime) {
removeCacheData(key);return null;
}if (maxVisitCount > 0 && (maxVisitCount - cacheData.getCount()) <= 0) {
removeCacheData(key);return null;
}else{
cacheData.addCount();
}returncacheData.getData();
}/*** 当缓存中数据失效时,用不给定的方法线程更新数据
*@paramo 取得数据的对像(该方法是静态方法是不用实例,则传Class实列)
*@parammethodName 该对像中的方法
*@paramparameters 该方法的参数列表(参数列表中对像都要实现toString方法,若列表中某一参数为空则传它所属类的Class)
*@paramintervalTime 缓存的时间周期,小于等于0时不限制
*@parammaxVisitCount 访问累积次数,小于等于0时不限制
*@return
*/
publicObject getCacheData(Object o, String methodName,Object[] parameters,long intervalTime, intmaxVisitCount) {
Class oc= o instanceof Class ?(Class)o : o.getClass();
StringBuffer key= new StringBuffer(oc.getName());//生成缓存key值
key.append("-").append(methodName);if (parameters != null) {for (int i = 0; i < parameters.length; i++) {if (parameters[i] instanceofObject[]) {
key.append("-").append(Arrays.toString((Object[])parameters[i]));
}else{
key.append("-").append(parameters[i]);
}
}
}
CacheData cacheData=(CacheData)cacheMap.get(key.toString());if (cacheData == null) {//等待加载并返回
Object returnValue =invoke(o, methodName, parameters, key.toString());return returnValue instanceof Class ? null: returnValue;
}if (intervalTime > 0 && (System.currentTimeMillis() - cacheData.getTime()) >intervalTime) {
daemonInvoke(o, methodName, parameters, key.toString());//缓存时间超时,启动线程更新数据
} else if (maxVisitCount > 0 && (maxVisitCount - cacheData.getCount()) <= 0) {//访问次数超出,启动线程更新数据
daemonInvoke(o, methodName, parameters, key.toString());
}else{
cacheData.addCount();
}returncacheData.getData();
}/*** 递归调用给定方法更新缓存中数据据
*@paramo
*@parammethodName
*@paramparameters
*@paramkey
*@return若反射调用方法返回值为空则返回该值的类型*/
privateObject invoke(Object o, String methodName,Object[] parameters, String key) {
Object returnValue= null;try{
Class[] pcs= null;if (parameters != null) {
pcs= newClass[parameters.length];for (int i = 0; i < parameters.length; i++) {if (parameters[i] instanceofMethodInfo) {//参数类型是MethodInfo则调用该方法的返回值做这参数
MethodInfo pmi =(MethodInfo)parameters[i];
Object pre= invoke(pmi.getO(), pmi.getMethodName(), pmi.getParameters(), null);
parameters[i]=pre;
}if (parameters[i] instanceofClass) {
pcs[i]=(Class)parameters[i];
parameters[i]= null;
}else{
pcs[i]=parameters[i].getClass();
}
}
}
Class oc= o instanceof Class ?(Class)o : o.getClass();//Method m = oc.getDeclaredMethod(methodName, pcs);
Method m =matchMethod(oc, methodName, pcs);
Object o1= oc.newInstance(); //add by chf
returnValue =m.invoke(o1, parameters);if (key != null && returnValue != null) {
addCacheData(key, returnValue,false);
}if (returnValue == null) {
returnValue=m.getReturnType();
}
}catch(Exception e) {
log.error("调用方法失败,methodName=" +methodName);if (key != null) {
removeCacheData(key);
log.error("更新缓存失败,缓存key=" +key);
}
e.printStackTrace();
}returnreturnValue;
}/*** 找不到完全匹配的方法时,对参数进行向父类匹配
* 因为方法aa(java.util.List) 与 aa(java.util.ArrayList)不能自动匹配到
*
*@paramoc
*@parammethodName
*@parampcs
*@return*@throwsNoSuchMethodException
*@throwsNoSuchMethodException*/
privateMethod matchMethod(Class oc, String methodName, Class[] pcs
)throwsNoSuchMethodException, SecurityException {try{
Method method=oc.getDeclaredMethod(methodName, pcs);returnmethod;
}catch(NoSuchMethodException e) {
Method[] ms=oc.getDeclaredMethods();
aa:for (int i = 0; i < ms.length; i++) {if(ms[i].getName().equals(methodName)) {
Class[] pts=ms[i].getParameterTypes();if (pts.length ==pcs.length) {for (int j = 0; j < pts.length; j++) {if (!pts[j].isAssignableFrom(pcs[j])) {breakaa;
}
}returnms[i];
}
}
}throw newNoSuchMethodException();
}
}/*** 新启线程后台调用给定方法更新缓存中数据据
*@paramo
*@parammethodName
*@paramparameters
*@paramkey*/
private voiddaemonInvoke(Object o, String methodName,Object[] parameters, String key) {if (!threadKeys.contains(key)) {
InvokeThread t= newInvokeThread(o, methodName, parameters, key);
t.start();
}
}