123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /** Copyright 2009 by primeton Corporation.
- *
- * All rights reserved.
- *
- * This software is the confidential and proprietary information of
- * primeton Corporation ('Confidential Information'). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with primeton.
- */
- package com.primeton.dgs.kernel.core.cache.impl;
- import java.lang.reflect.Method;
- import java.security.MessageDigest;
- import java.util.HashMap;
- import java.util.Map;
- import com.primeton.dgs.kernel.core.cache.CacheEvict;
- import com.primeton.dgs.kernel.core.cache.Cacheable;
- import com.primeton.dgs.kernel.core.util.StringFullUtils;
- import org.apache.commons.lang.StringUtils;
- import org.apache.commons.lang3.SystemUtils;
- import org.aspectj.lang.ProceedingJoinPoint;
- import com.primeton.dgs.kernel.core.cache.ICache;
- import com.primeton.dgs.kernel.core.cache.ICacheInterceptor;
- import com.primeton.dgs.kernel.core.cache.ICacheKeyCreator;
- import org.aspectj.lang.Signature;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * @author xiongbin
- * @author zhaopx 缓存拦截器
- * @Version 2012-8-28
- */
- public class CacheInterceptorImpl implements ICacheInterceptor {
- private static final Logger log = LoggerFactory.getLogger(CacheInterceptorImpl.class);
- /**
- * 缓存
- */
- private ICache<Object> cache;
- /**
- * 缓存的 Key 生成逻辑管理器
- */
- private DefaultCacheKeyCreatorManager manager;
- public Object add(ProceedingJoinPoint jp){
- try {
- Object[] args = jp.getArgs();
- // 通过 AOP 拦截的类全名,获得该类的 ICacheKeyCreator,缓存 ID 生成器
- // ICacheKeyCreator 一定是非空的
- ICacheKeyCreator creator = manager.getCacheKeyCreator(jp.getTarget().getClass().getName());
- // 获取到该方法需要缓存的 Name
- String methodName = jp.getSignature().getName();
- // 通过参数生成缓存 ID
- String key = getKey(creator.getCacheKey(args));
- if(StringUtils.isNotBlank(key)){
- final String cacheKey = methodName + "_" + key;
- synchronized (this) {
- Object result = cache.get(cacheKey);
- if(result == null){
- result = jp.proceed();
- // 调用取得返回值缓存,如果是从缓存中取出,无须继续放入缓存,减少
- cache.add(cacheKey, creator.getExpTime(methodName), result);
- }
- return result;
- }
- }
- // 无参数函数无法缓存,或者缓存的 Key 无法生成,不缓存
- return jp.proceed();
- } catch (Throwable e) {
- log.error("AOP 调用接口异常。", e);
- throw new IllegalStateException(e);
- }
- }
- /**
- * 根据 接口的注解支持缓存
- *
- * add zhaopx at: 2019/09/24
- * @param jp
- * @return
- */
- public Object cachedAnno(ProceedingJoinPoint jp){
- try {
- Object[] args = jp.getArgs();
- Class<?> aClass = jp.getTarget().getClass();
- Signature signature = jp.getSignature();
- String methodName = signature.getName();
- MethodSignature msig = null;
- if (!(signature instanceof MethodSignature)) {
- throw new IllegalArgumentException("该注解只能用于方法");
- }
- msig = (MethodSignature) signature;
- Class[] parameterTypes = msig.getParameterTypes();
- Method cachedMethod = aClass.getMethod(msig.getName(), parameterTypes);
- // 方法参数,构成一个 Map,用于拼接 Cache key
- final Map<String, String> argsMap = new HashMap<>(parameterTypes.length);
- argsMap.put("methodName", methodName);
- argsMap.put("className", aClass.getSimpleName());
- for (int i = 0; i < args.length; i++) {
- String argValue = (args[i] == null ? "" : String.valueOf(args[i]));
- argsMap.put("arg" + i, argValue);
- }
- // JDK8 才执行
- if(SystemUtils.IS_JAVA_1_8) {
- int i = 0;
- // 这样的方式导入,否则 JDK7 一下报错
- java.lang.reflect.Parameter[] parameters = cachedMethod.getParameters();
- for (java.lang.reflect.Parameter parameter : parameters) {
- String argValue = (args[i] == null ? "" : String.valueOf(args[i]));
- argsMap.put(parameter.getName(), argValue);
- i++;
- }
- }
- // 删除缓存的策略
- CacheEvict cacheEvictAnno = cachedMethod.getAnnotation(CacheEvict.class);
- if(cacheEvictAnno != null) {
- if(cacheEvictAnno.allEntries()) {
- // 删除所有缓存键
- cache.clear();
- } else {
- String[] keys = cacheEvictAnno.keys();
- for (String key : keys) {
- // 依次删除所有缓存 Key
- // 宏替换,替换 ${} 内的变量
- key = StringFullUtils.getFullString(key, argsMap);
- cache.remove(key);
- log.warn("remove cache key {}", key);
- }
- // 前缀删除,当前还看怎么支持
- if(StringUtils.isNotBlank(cacheEvictAnno.keyPrefix())) {
- try {
- cache.removeByPrefix(cacheEvictAnno.keyPrefix());
- } catch (Exception e) {}
- }
- }
- }
- // 获取方法注解
- Cacheable cachedAnno = cachedMethod.getAnnotation(Cacheable.class);
- if(cachedAnno == null) {
- // 接口上没有 Cacheable 的注解,不进行缓存
- // log.info("execute no cache method {}.{}", aClass.getName(), methodName);
- // 无参数函数无法缓存,或者缓存的 Key 无法生成,不缓存
- return jp.proceed();
- } else {
- final long start = System.currentTimeMillis();
- String key = cachedAnno.key();
- // 宏替换,替换 ${} 内的变量
- key = StringFullUtils.getFullString(key, argsMap);
- Object result = cache.get(key);
- if(result == null){
- log.info("no cache key {}, execute method {}.{}", key, aClass.getName(), methodName);
- result = jp.proceed();
- if(cachedAnno.expire() > 0) {
- // 有缓存过期时间的
- cache.add(key, cachedAnno.expire(), result);
- } else {
- cache.add(key, result);
- }
- } else {
- log.info("cached key {}, return result from cache(exe {}, cost time {} ms).",
- key,
- methodName,
- (System.currentTimeMillis() - start));
- }
- return result;
- }
- } catch (Throwable e) {
- log.error("AOP 调用接口异常。", e);
- throw new IllegalStateException(e.getMessage());
- }
- }
- private String getKey(String key) {
- if(key.matches("[*:]")){
- return "";
- }
-
- System.out.println("memcachedKEY:"+key);
- try {
- key = encryptMD5(key);
- } catch (Exception e) {
- log.error("生成 md5 异常。", e);
- }
- return key;
- }
- public void refresh() {
- try {
- cache.clear();
- } catch (Exception e) {
- log.error("清除缓存异常。", e);
- }
- }
- public DefaultCacheKeyCreatorManager getManager() {
- return manager;
- }
- public void setManager(DefaultCacheKeyCreatorManager manager) {
- this.manager = manager;
- }
- public ICache getCache() {
- return cache;
- }
- public void setCache(ICache cache) {
- this.cache = cache;
- }
- /**
- * 使用MD5加密
- * @param originalText 明文
- * @return 密文
- * @throws Exception JDK不支持MD5加密算法
- */
- private String encryptMD5(String originalText) throws Exception {
- MessageDigest md5 = MessageDigest.getInstance("MD5");
- md5.update(originalText.getBytes());
- byte[] digest = md5.digest();
-
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < digest.length; i++) {
- String s = Integer.toHexString(digest[i] & 0XFF);
- if (s.length() == 1) {
- sb.append(i).append(s);
- } else {
- sb.append(s);
- }
- if (i < digest.length-1) {
- sb.append(i);
- }
- }
- return sb.toString().toUpperCase();
- }
- }
|