为了方便使用memcached缓存,特编写了aop注解工具实现缓存
1. 项目结构
2. 注解编写
import java.lang.annotation.*;
/**
* @author 赵超
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cached {
int value() default 60;//minute
}
3. CachedAop
import com.sys.job.util.StaticUtil;
import net.spy.memcached.MemcachedClient;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author 赵超
* @Description memcached缓存aop
* @create 2017-06-26 8:40
**/
@Aspect
public class CacheAop {
private static Logger logger = Logger.getLogger(CacheAop.class);
@Autowired
private MemcachedClient memcachedClient;
@Pointcut("@annotation(com.sys.job.cache.aop.Cached)")
public void cachedAspect() {
}
@Around(value = "cachedAspect()")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
int saveTime = 60;
// 获取方法名
Signature signature = pjp.getSignature();
String methodName = signature.getName();
String params = "(";
// 获取参数
Object[] args = pjp.getArgs();
for (Object object : args) {
params += object + "_";
}
params = params.contains("_") ? params.substring(0, params.length() - 1) : params;
String key = methodName + params + ")";
//获取方法的注解
Method targetMethod = ((MethodSignature)signature).getMethod();
Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(methodName,
targetMethod.getParameterTypes());
if (realMethod.isAnnotationPresent(Cached.class)) {
Cached cached = realMethod.getAnnotation(Cached.class);
saveTime *= cached.value();
}
Object proceed;
if (StaticUtil.USE_MEMCACHED && memcachedClient.get(key) != null) {
try {
proceed = memcachedClient.get(key);
logger.info("CacheAop memcached: " + key);
} catch (Exception e) {
proceed = pjp.proceed(args);
memcachedClient.add(key, saveTime, proceed);
add(memcachedClient, methodName, saveTime, key);
logger.error("memcachedError", e);
}
} else {
proceed = pjp.proceed(args);
if (StaticUtil.USE_MEMCACHED && memcachedClient.get(key) == null) {
add(memcachedClient, methodName, saveTime, key);
memcachedClient.add(key, saveTime, proceed);
}
}
return proceed;
}
private static void add(MemcachedClient memcachedClient, String methodName,
int saveSeconds, String key) {
Map<String, Set<String>> save;
Set<String> set;
//判断memcached中是否存在key管理StaticUtil.memcachedKeys
if (memcachedClient.get(StaticUtil.memcachedKeys) != null) {
save = (Map<String, Set<String>>) memcachedClient.get(StaticUtil.memcachedKeys);
} else {
save = new HashMap<>();
}
if (save.containsKey(methodName) && save.get(methodName) != null) {
set = save.get(methodName);
} else {
set = new HashSet<>();
}
set.add(key);
logger.info("CacheAop Add save " + saveSeconds / 60 + "minutes memcached: " + key);
save.put(methodName, set);
if (memcachedClient.get(StaticUtil.memcachedKeys) != null) {
memcachedClient.replace(StaticUtil.memcachedKeys, 60 * 60 * 24, save);
} else {
memcachedClient.add(StaticUtil.memcachedKeys, 60 * 60 * 24, save);
}
logger.info("StaticUtil.memcachedKeys " + memcachedClient.get(StaticUtil.memcachedKeys));
}
}
4. MemcachedUtil中的有效方法
/**
* 删除memcached数据
* @param memcachedClient
* @param memcachedKey StaticUtil.memcachedKeys的key,作用类似于redis的field
* @return
*/
public static Integer delete(MemcachedClient memcachedClient, String memcachedKey) {
try {
if (memcachedClient.get(StaticUtil.memcachedKeys) != null) {
Map<String, Set<String>> save =
(Map<String, Set<String>>) memcachedClient.get(StaticUtil.memcachedKeys);
if (save.containsKey(memcachedKey) && save.get(memcachedKey) != null) {
Set<String> set = save.get(memcachedKey);
set.forEach(s -> memcachedClient.delete(s.toString()));
save.remove(memcachedKey);
memcachedClient.replace(StaticUtil.memcachedKeys, 60 * 60 * 24, save);
return 1;
}
}
return 0;
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
5. 使用
@Cached(30)
@Override
public Map getBlogList(String up, String scan, String time, String class_,
String info, Integer page, Integer limit) throws Exception {
Map<String, Object> back = new HashMap(5);
PageHelper.startPage(page, limit);
Page<Blog> res = blogDao.getBlogList(up, scan, time, class_, info);
back.put("resCode", res != null ? 1 : -1);
back.put("resData", res.getResult());
back.put("sumPage", res.getPages());
back.put("sumCount", res.getTotal());
return back;
}
6. 控制台