AOP实现Memcached注解缓存

本文介绍了一种利用AOP注解技术实现Memcached缓存管理的方法,通过自定义注解和AspectJ切面,实现了方法级别的缓存控制,支持缓存有效期设置,并提供了缓存更新和清理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了方便使用memcached缓存,特编写了aop注解工具实现缓存

1. 项目结构

blob.png


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. 控制台

blob.png


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpongo11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值