EJB3.0_方法缓存
公司维护的系统,涉及好多权限管理,区域信息,公共配置信息,之前系统都是通过缓存去读取这些配置信息,现在为了满足定制,开发了各种管理功能,这样就导致之前从缓存中读取的信息无法取到最新。
?
于是考虑用Ehcache来实现方法缓存,这个在spring 中整合是非常简单的,这边考虑在Ejb3中整合Ehcache。
?
废话不说,直接代码,demo 如下:
?
定义注解
?
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Cache{ public CacheFlag value();}?
?
定义注解取值
public enum CacheFlag{ /** * 添加缓存 */ ADD, /** * 删除缓存 */ DELETE}
?
缓存处理实例
/** * Ehcache Handler * * @author * @version [版本号, 2011-3-13] * @see [相关类/方法] * @since [产品/模块版本] */public class CacheHandler{ /** * 实例 */ public volatile static CacheHandler cacheHandler = null; /** * cache 名称 */ private static final String CACHE_NAME = "methodCache"; private CacheManager cacheManager = null; private net.sf.ehcache.Cache cache = null; private boolean status = false; private static Map<String, List<String>> ADDCACHEMAP =? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? new HashMap<String, List<String>>(); private static Map<String, List<String>> DELETECACHEMAP = ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?new HashMap<String, List<String>>(); private CacheHandler() { initCache(); } private void initCache() { cacheManager = new CacheManager(Thread.currentThread() .getContextClassLoader() .getResourceAsStream("conf/cache/ehcache.xml")); cache = cacheManager.getCache(CACHE_NAME); if (null != cache) { status = true; } } public void checkCacheStatus(Method method) { String className = method.getDeclaringClass().toString(); List<String> localStatus = ADDCACHEMAP.get(className); if (null == localStatus) { initCacheForClass(method); // 初始化 } } /** * 初始化缓存 * @param method * Method * @return void [返回类型说明] * @exception throws [违例类型] [违例说明] * @see [类、类#方法、类#成员] */ private void initCacheForClass(Method method) { List<String> methodCache = null; String methodInfo = null; String className = method.getDeclaringClass().toString(); Method[] arrayOfMethod = method.getDeclaringClass().getMethods(); for (Method med : arrayOfMethod) { com.xxx.util.cache.Cache cacheAnnotation = med.getAnnotation(com.xxx.util.cache.Cache.class); if (null != cacheAnnotation) { if (cacheAnnotation.value().equals(CacheFlag.ADD)) { methodCache = ADDCACHEMAP.get(method.getDeclaringClass().toString()); if (null == methodCache) { methodCache = new ArrayList<String>(); ADDCACHEMAP.put(className, methodCache); } methodInfo = med.getName() + ":" + Arrays.toString(med.getParameterTypes()); methodCache.add(methodInfo); } else if (cacheAnnotation.value().equals(CacheFlag.DELETE)) { methodCache = DELETECACHEMAP.get(method.getDeclaringClass().toString()); if (null == methodCache) { methodCache = new ArrayList<String>(); DELETECACHEMAP.put(className, methodCache); } methodInfo = med.getName() + ":" + Arrays.toString(med.getParameterTypes()); methodCache.add(methodInfo); } } } } /** * 获取 Cache key * @param className * @param methodName * @param paramArrayOfObject * @return [参数说明] * * @return String [返回类型说明] * @exception throws [违例类型] [违例说明] * @see [类、类#方法、类#成员] */ protected String getCacheKey(String className, String methodName,? ? ? ? ? ?Object[] paramArrayOfObject) { StringBuffer cacheKey = new StringBuffer(); cacheKey.append(className).append(".").append(methodName); if ((paramArrayOfObject != null) && (paramArrayOfObject.length != 0)) { for (int i = 0; i < paramArrayOfObject.length; ++i) { if (paramArrayOfObject[i] != null) { cacheKey.append(".").append(getArgumentString(paramArrayOfObject[i])); } else { cacheKey.append(".null"); } } } return cacheKey.toString(); } @SuppressWarnings("unchecked") private String getArgumentString(Object paramObject) { Class localClass = paramObject.getClass(); if (localClass.isArray()) { if (localClass.isAssignableFrom(Integer.class)) { return Arrays.toString((int[]) (int[]) paramObject); } if (localClass.isAssignableFrom(Boolean.class)) { return Arrays.toString((boolean[]) (boolean[]) paramObject); } return Arrays.toString((Object[]) (Object[]) paramObject); } return paramObject.toString(); } public boolean isCache(InvocationContext invocationContext) { Cache cacheFlag = invocationContext.getMethod().getAnnotation(Cache.class); if (null != cacheFlag) { if (cacheFlag.value().equals(CacheFlag.ADD)) { return true; } } return false; } public boolean isClear(InvocationContext invocationContext) { Cache cacheFlag = invocationContext.getMethod().getAnnotation(Cache.class); if (null != cacheFlag) { if (cacheFlag.value().equals(CacheFlag.DELETE)) { return true; } } return false; } public void clearCache() { net.sf.ehcache.Cache cache = cacheManager.getCache(CACHE_NAME); cache.removeAll(); } public static CacheHandler getInstance() { if (null == cacheHandler) { synchronized (CacheHandler.class) { if (null == cacheHandler) { cacheHandler = new CacheHandler(); } } } return cacheHandler; } public boolean isEnable() { return status; } public synchronized void destroy() { cacheManager.shutdown(); status = false; } public Object getCacheElement(String cacheKey) throws CloneNotSupportedException { Element element = cache.get(cacheKey); if (null != element) { return ((Element) element.clone()).getValue(); } return null; } public void addResult(String cacheKey, Object cacheValue) { Element element = new Element(cacheKey, cacheValue); this.cache.put(element); } }?
?
?EJB 拦截器定义
?
public class CacheInterceptor{ @AroundInvoke public Object cacheProcess(InvocationContext invocationContext) throws Exception { Object result = null; CacheHandler cacheHandler = CacheHandler.getInstance(); if (cacheHandler.isEnable()) { boolean isCache = cacheHandler.isCache(invocationContext); boolean isClear = cacheHandler.isClear(invocationContext); if (!isCache && !isClear) { result = invocationContext.proceed(); return result; } // 清空缓存 if (isClear) { cacheHandler.clearCache(); result = invocationContext.proceed(); return result; } if (isCache) { String className = invocationContext.getMethod().getDeclaringClass().getName(); String methodName = invocationContext.getMethod().getName(); Object[] paramArrayOfObject = invocationContext.getParameters(); // Cache key String cacheKey = cacheHandler.getCacheKey(className, methodName, paramArrayOfObject); try { result = cacheHandler.getCacheElement(cacheKey); if (null == result) { result = invocationContext.proceed(); cacheHandler.addResult(cacheKey, result); } } catch (Exception e) { result = invocationContext.proceed(); } return result; } } else { result = invocationContext.proceed(); return result; } return invocationContext.proceed(); }}
?
EJB 方法使用
?
@Override @Interceptors(CacheInterceptor.class) @Cache(CacheFlag.ADD) public CabinDomain queryCabinInfo(CabinPK cabinPK) { return entityManager.find(CabinDomain.class, cabinPK); }?
?
@Override @Interceptors(CacheInterceptor.class) @Cache(CacheFlag.DELETE) public void addCabinInfo(CabinDomain cabinDomain) { entityManager.persist(cabinDomain); }
?
其他:部署在Jboss上
?
?
简单的demo,大家觉的,有哪些地方需要改进的?
1 楼 smallsnake 2011-03-23 :D 针对大量的数据,可以写个公共的缓存的机制 2 楼 pch272215690 2012-02-02 真实项目中用过吗?我最近也想搞个类似的,就是key生成方式没有想到。