SpringBoot 注解调用Redis缓存
注解代码:
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by qhong on 2018/9/5 11:12
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface CreditRedisCache {
String prefix() default "huishi-server:credit";
}
利用拦截器处理注解中的方法,有就调用缓存,没有就新增
import com.alibaba.fastjson.JSON;
import com.shitou.huishi.annotation.CreditRedisCache;
import com.shitou.huishi.utils.RedisUtil;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
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 org.springframework.stereotype.Component;
/**
* Created by qhong on 2018/9/5 11:13
**/
@Aspect
@Component
@Slf4j
public class RedisCacheAspect {
@Autowired
RedisUtil redisUtil;
/**
* 分隔符 生成key 格式为 类全类名|方法名|参数所属类全类名
**/
private static final String DELIMITER = "-";
private static final Long expireTime=60*60*24*30L;
/**
* Service层切点 使用到了我们定义的 RedisCache 作为切点表达式。
* 而且我们可以看出此表达式基于 annotation。
* 并且用于内建属性为查询的方法之上
*/
@Pointcut("@annotation(com.shitou.huishi.annotation.CreditRedisCache)")
public void redisCacheAspect() {
}
/**
* Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
* <p>
* 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
*
* @param pjp the pjp
* @return object
* @throws Throwable the throwable
*/
@Around(value = "redisCacheAspect()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 得到类名、方法名和参数
String clazzName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
// 根据类名、方法名和参数生成Key
log.info("key参数: " + clazzName + "." + methodName);
String key = getKey(clazzName, methodName, args);
if (log.isInfoEnabled()) {
log.info("生成key: " + key);
}
// 得到被代理的方法
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
//redis 前缀
String prefix = method.getAnnotation(CreditRedisCache.class).prefix();
// 检查Redis中是否有缓存
Object value = redisUtil.get(prefix, key);
// 得到被代理方法的返回值类型
Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType();
// result是方法的最终返回结果
Object result = null;
try {
if (null == value) {
log.info("缓存未命中");
// 调用数据库查询方法
result = joinPoint.proceed(args);
// 结果放入缓存
redisUtil.set(prefix, key, result,expireTime);
} else {
// 缓存命中
log.info("缓存命中, value = " + JSON.toJSONString(value));
result = value;
}
} catch (Throwable e) {
log.error("程序异常",e.getMessage());
throw e;
}
return result;
}
/**
* * 根据类名、方法名和参数生成Key
* * @param clazzName
* * @param methodName
* * @param args
* * @return key格式:全类名|方法名|参数类型
*
*/
private String getKey(String clazzName, String methodName, Object[] args) {
StringBuilder key = new StringBuilder(clazzName);
key.append(DELIMITER);
key.append(methodName);
key.append(DELIMITER);
key.append(Arrays.stream(args).map(x->x.toString()).collect(Collectors.joining(DELIMITER)));
return key.toString();
}
}
使用:
@CreditRedisCache
public DataResponse queryICInfo(String name,String card)
直接在方法上使用即可,如果要自定义前缀,可以添加prefix,不然使用默认值。
这种很类似Spring-Cache,但是自己的代码比较灵活 ,可以针对不同的模块设定前缀,缓存时间等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)