AOP实现Redis注解缓存(支持各种配置)

摘自:https://www.zhaochao.top/article/179,更多开发技术请访问 https://www.zhaochao.top

首先编写@Cached注解 

import com.common.redis.RedisDBEnum;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cached {
    int expire() default 60;//second

    @AliasFor("key")
    String value() default "";

    @AliasFor("value")
    String key() default "";

    RedisDBEnum database() default RedisDBEnum.SYS;
}

 编写核心Aop缓存任务

import com.alibaba.fastjson.JSON;
import com.common.redis.RedisDBEnum;
import com.environment.ds.annotation.Cached;
import com.environment.redis.impl.RedisRepositoryImpl;
import org.apache.commons.lang3.StringUtils;
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 org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Aspect
@Component
public class CacheAop {

    @Autowired
    private RedisRepositoryImpl redis;
    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = 
                                                 new LocalVariableTableParameterNameDiscoverer();

    @Pointcut("@annotation(com.ymt.crmservice.environment.ds.annotation.Cached)")
    public void cachedAspect() {
    }

    @Around(value = "cachedAspect()")
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
        // 获取方法名
        Signature signature = pjp.getSignature();
        String methodName = signature.getName();
        Object[] args = pjp.getArgs();
        //获取方法的注解
        Method targetMethod = ((MethodSignature) signature).getMethod();
        Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(methodName,
                targetMethod.getParameterTypes());
        Map params = new HashMap<>();
        params.put("methodName", methodName);
        params.put("fullName", targetMethod.getDeclaringClass().getName());
        params.put("simpleName", targetMethod.getDeclaringClass().getSimpleName());
        Cached cached = realMethod.getAnnotation(Cached.class);
        String[] paramList = discoverer.getParameterNames(targetMethod);
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariables(params);
        for (int len = 0; len < paramList.length; len++) {
            context.setVariable(paramList[len], args[len]);
        }
        Expression expression = parser.parseExpression(cached.key());
        String key = expression.getValue(context, String.class);
        int saveTime = cached.expire();
        RedisDBEnum database = cached.database();
        Type type = realMethod.getGenericReturnType();
        Object proceed;
        String str = redis.get(RedisDBEnum.SYS, key);
        //命中缓存
        if (StringUtils.isNotBlank(str)) {
            Class returnClass = realMethod.getReturnType();
            // 返回值数据类型是否为List
            if (realMethod.getReturnType() == List.class) {//List
                //为List则获取泛型的实际类型
                if (type instanceof ParameterizedType) {
                    Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
                    returnClass = Class.forName(actualTypeArguments[0].getTypeName());
                }
                proceed = JSON.parseArray(str, returnClass);
            } else {//其他数据类型
                proceed = JSON.parseObject(str, returnClass);
            }
            return proceed;
        }
        //未命中缓存
        proceed = pjp.proceed(args);
        if (proceed != null) {
            redis.set(database, key, JSON.toJSONString(proceed), saveTime);
        }
        return proceed;
    }
}

测试使用

    @Cached(database = RedisDBEnum.SYS, expire = 100, 
            key = "#fullName + ':' + #methodName + ':' + #dictTypeCode + ':' + #parentCode")
    @Override
    public List list(String dictTypeCode, String parentCode) {
        // TODO 具体实现
        return null;
    }

 这个是出初始版本,可以结合Gson进行优化等等!

 

你可能感兴趣的:(web,springboot,java,aop)