一,情景介绍
公司新需求,在查询接口的manager层要加入redis缓存,只要通过manager层的增删改查方法,统统进行缓存处理。
基于这个需求,我写了一个aop切面,具体实现逻辑如下
ProceedingJoinPoint的操作见文章:https://www.cnblogs.com/draymond/p/12670123.html
二,思路梳理
大致分为以下几个步骤,不多,很简单
- 自定义注解,凡是在Manager层加该注解的方法,都要进行缓存
- aop切面,切该注解
- 判断操作类型(增删改查),得到key值
- 对操作结果进行缓存
三,代码实践
1,自定义注解
@Target({
ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)//选择运行环境
public @interface E2eCache {
//查询条件(查询详情的主键)
String key();
/**
* 方法操作
* 默认为查询操作 新增指定为[add] 更新指定为[edit] 删除指定为[del] 查询指定为[get]
* @return
*/
String operate() default "get";
}
2,切面类
/**
* redis在manager层的切面类,作为缓存机制,达到以下目的
* 1,判断当前环境是否存在redis,如果存在,则加载缓存机制,如果不存在,则按原逻辑进行
* 2,增删改查均加入redis缓存
* 3,考虑对原有代码不侵入的原则
*/
@Aspect
@Component
public class ManagerAspect {
@Value("spring.redis.host")
private String redisHost;
//TODO 模拟redis缓存,调试通过放RedisTemplate
private static Map<String,Object> redisTemplate=new HashMap<>();
private Logger logger= LoggerFactory.getLogger(ManagerAspect.class);
@Pointcut("@annotation(com.dayouzc.rediscache.annotation.E2eCache)")
private void cutMethod(){
}
@Around("cutMethod()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
//取注解的操作值
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//判断当前方法是否是在Manager类中
// todo 目前暂时是通过判断当前类是否存在@Repository注解,以及方法名是否包含Manager字符串
Class<?> declaringClass = signature.getMethod().getDeclaringClass();
String declaringClassName = declaringClass.getName();
//如果该方法不是在Manager类,不缓存
if(!declaringClass.isAnnotationPresent(Repository.class) || !declaringClassName.contains("Manager")){
return joinPoint.proceed();
}
// 1,判断是否存在redis环境
if(StringUtils.isBlank("test")){
logger.info("======== 当前环境redis不存在,缓存机制失效 ==========");
//原逻辑处理
return joinPoint.proceed();
}else{
logger.info("======== 当前环境redis正常,开启Manger层缓存 ==========");
//得到request请求
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//2,走redis缓存
E2eCache annotation = signature.getMethod().getAnnotation(E2eCache.class);
//操作类型
String operate = annotation.operate();
//key的名称
String id = annotation.key();
//方法名
String methodName = joinPoint.getSignature().getName();
//原方法返回值类型
Class returnType = signature.getReturnType();
if(operate.equals("get")){
//查询详情
JSONObject jsonObject = getByArgs(joinPoint, request);
//根据返回值类型返回对应的实体对象
Object object = JSONObject.toJavaObject(jsonObject, returnType);
return object;
}else if(operate.equals("add")){
//新增
JSONObject jsonObject = addOperation(joinPoint, request);
Object object = JSONObject.toJavaObject(jsonObject, returnType);