利用Spring的AOP,通过注解自动给方法添加缓存

2021-01-28  本文已影响0人  和平菌

需求:如果入参一致的情况下,返回值一致,那么可以给该方法添加缓存。但是,如果挨个添加每次添加都需要开发、测试,浪费大量时间。
解决方案:利用Spring的AOP,自动添加缓存功能

实现步骤:
1、定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface AutoCache {

    /**
     * 过期时间,单位是秒,默认1分钟
     * @return
     */
    int expire() default 60;

    /**
     * 是否延期,如果选择是,每次访问都会续期expire时长
     * @return
     */
    boolean isDelay() default  false;

    String version() default "";
}

一共3个参数:
过期时间
是否延期
方法的版本号

2、AOP拦截器

@Aspect
@Component
@Slf4j
public class CacheIntercepter {

    public static final String CACHE_KEY_PREFIX = "AUTOCACHE";
    
    @Autowired
    private ResultCache resultCache;

    @Around("@annotation(com.heping.aopcache.AutoCache)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        AutoCache methodCache = getAnnotation(joinPoint, AutoCache.class);
        String cacheKey = getCacheKey(joinPoint);

        String version = methodCache.version();
        if(version != null && version.length() > 0){
            cacheKey = cacheKey + version;
        }

        Object obj = resultCache.get(cacheKey);
        if (obj != null) {
            if(methodCache.isDelay()){
                resultCache.expire(cacheKey, methodCache.expire());
            }
            log.info("自动从缓存获取结果,key [{}]", cacheKey);
            return obj;
        } else {
            log.debug("没有命中缓存,key [{}]", cacheKey);
            Object result = joinPoint.proceed(joinPoint.getArgs());
            if (result == null) {
                log.error("从缓存获取到的结果为空,key [{}]", cacheKey);
            } else {
                resultCache.save(cacheKey, result, methodCache.expire());
            }
            return result;
        }
    }



    private String getCacheKey(ProceedingJoinPoint joinPoint) {
        return Tool.format("{}-{}.{}",
                CACHE_KEY_PREFIX,
                joinPoint.getSignature().toString().split("\\s")[1],
                StringUtils.join(joinPoint.getArgs(), ",")
        );
    }

    private <T extends Annotation> T getAnnotation(ProceedingJoinPoint jp, Class<T> clazz) {
        MethodSignature sign = (MethodSignature) jp.getSignature();
        Method method = sign.getMethod();
        return method.getAnnotation(clazz);
    }

}

其中ResultCache是对缓存读写的封装

3、使用例子

@AutoCache( expire = 10 * 60, isDelay = true, version = "v1")
    public String getName(String name){
        log.info("没有从缓存获取数据");
        return "jdtbi say:" + name;
    }

每次修改了方法,逻辑改变的时候,我们只需要修改注解上的version的值,那么我们就会自动刷新缓存了

上一篇下一篇

猜你喜欢

热点阅读