大致就是使用aop 及SpEL。本例基于jdk1.8,直接上代码。
@Target({ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface RedisCache {
RedisKeyEnum redisKeyEnum();
/**
* SpEL 编写
*
* @return
*/
String[] dynamicFields() default {};
/**
* 缓存的条件,可以为空,使用 SpEL 编写
* 为空则默认执行缓存操作
*
* @return
*/
String condition() default "";
}
@Getter
@AllArgsConstructor
public enum RedisKeyEnum {
EVENT_MSG_LOG("msg_log:{0}", "事件消息日志", 60 * 60);
private String key;
private String desc;
/**
* 默认失效时间(秒)
*/
private Integer failureTime;
public String getCacheKey(String... param) {
StringBuilder stringBuilder = new StringBuilder("event:");
if (param == null || param.length == 0) {
return stringBuilder.append(this.getKey()).toString();
}
stringBuilder.append(MessageFormat.format(this.getKey(), param)).toString();
return stringBuilder.toString();
}
}
@Aspect
@Component
@Slf4j
public class RedisAspect {
@Autowired
private JedisCluster jedisCluster;
@Pointcut("execution(* com.xxx.event.service.impl..*.*(..))")
public void cachePointcut() {
}
/**
* put 缓存
*
* @param pj
* @param putRedisCache
* @throws Throwable
*/
@AfterReturning(returning = "result", pointcut = "cachePointcut() && @annotation(putRedisCache)")
public void doPut(JoinPoint pj, Object result, RedisCachePut putRedisCache) {
if (putRedisCache.putCaches() == null || putRedisCache.putCaches().length == 0) {
return;
}
if (result == null) {
return;
}
StandardEvaluationContext standardEvaluationContext = null;
ExpressionParser parser = null;
for (RedisCache redisCache : putRedisCache.putCaches()) {
if (!isEnableCacheAction(redisCache, pj, parser, standardEvaluationContext)) {
continue;
}
String redisKey = buildRedisKey(redisCache,pj, parser, standardEvaluationContext);
save2Redis(redisKey, redisCache, result);
}
}
/**
* 清理缓存
*
* @param pj
* @param clearRedisCache
*/
@After("cachePointcut() && @annotation(clearRedisCache)")
public void doClear(JoinPoint pj, RedisCacheClear clearRedisCache) {
if (clearRedisCache.clearCaches() == null || clearRedisCache.clearCaches().length == 0) {
return;
}
StandardEvaluationContext standardEvaluationContext = null;
ExpressionParser parser = null;
for (RedisCache redisCache : clearRedisCache.clearCaches()) {
if (!isEnableCacheAction(redisCache, pj, parser, standardEvaluationContext)) {
continue;
}
String redisKey = buildRedisKey(redisCache,pj, parser, standardEvaluationContext);
log.info("清理缓存key为:{}", redisKey);
jedisCluster.del(redisKey);
}
}
@Around("cachePointcut() && @annotation(redisCache)")
public Object doCache(ProceedingJoinPoint pj, RedisCache redisCache) throws Throwable {
StandardEvaluationContext standardEvaluationContext = null;
ExpressionParser parser = null;
if (!isEnableCacheAction(redisCache, pj, parser, standardEvaluationContext)) {
return pj.proceed();
}
String redisKey = buildRedisKey(redisCache,pj, parser, standardEvaluationContext);
String str = jedisCluster.get(redisKey);
if (!StringUtils.isBlank(str)) {
MethodSignature methodSignature = (MethodSignature) pj.getSignature();
log.info("方法:{}命中缓存key:{}", methodSignature.getMethod(), redisKey);
return JSON.parseObject(str, methodSignature.getMethod().getReturnType());
}
Object result = pj.proceed();
return save2Redis(redisKey, redisCache, result);
}
private Object save2Redis(String redisKey, RedisCache redisCache, Object result) {
if (result == null) {
return result;
}
String str = JSON.toJSONString(result);
if (redisCache.redisKeyEnum().getFailureTime() != null) {
jedisCluster.setex(redisKey, redisCache.redisKeyEnum().getFailureTime(), str);
} else {
jedisCluster.set(redisKey, str);
}
return result;
}
/**
* 构建缓存key
*
* @param redisCache
* @param parser
* @param standardEvaluationContext
* @return
*/
private String buildRedisKey(RedisCache redisCache,JoinPoint pj, ExpressionParser parser, StandardEvaluationContext standardEvaluationContext) {
String[] dynamicFields = redisCache.dynamicFields();
if (dynamicFields == null || dynamicFields.length == 0) {
return redisCache.redisKeyEnum().getCacheKey();
}
if (parser == null) {
parser = new SpelExpressionParser();
}
if (standardEvaluationContext == null) {
standardEvaluationContext = initContextVariables(pj);
}
String[] replaceFieldVal = new String[dynamicFields.length];
for (int i = 0; i < dynamicFields.length; i++) {
replaceFieldVal[i] = parser.parseExpression(dynamicFields[i]).getValue(standardEvaluationContext, Object.class).toString();
}
return redisCache.redisKeyEnum().getCacheKey(replaceFieldVal);
}
private boolean isEnableCacheAction(RedisCache redisCache, JoinPoint pj, ExpressionParser parser, StandardEvaluationContext standardEvaluationContext) {
if (StringUtils.isBlank(redisCache.condition())) {
return Boolean.TRUE;
}
if (parser == null) {
parser = new SpelExpressionParser();
}
if (standardEvaluationContext == null) {
standardEvaluationContext = initContextVariables(pj);
}
return parser.parseExpression(redisCache.condition()).getValue(standardEvaluationContext, Boolean.class);
}
private StandardEvaluationContext initContextVariables(JoinPoint joinPoint) {
StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext();
Object[] args = joinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] parametersName = methodSignature.getParameterNames();
if (args == null || args.length <= 0) {
return standardEvaluationContext;
}
for (int i = 0; i < args.length; i++) {
standardEvaluationContext.setVariable(parametersName[i], args[i]);
}
return standardEvaluationContext;
}
}
使用
@RedisCache(redisKeyEnum = RedisKeyEnum.EVENT_MSG_LOG, dynamicFields = {"#msgId"})
public EventMsgLog selectByMsgId(String msgId) {
log.info("查询消息日志记录");
return eventMsgLogMapper.selectByMsgId(msgId);
}