美文网首页Cache
Spring自带整合redis缓存注解

Spring自带整合redis缓存注解

作者: 夜阑人儿未静 | 来源:发表于2018-12-07 22:05 被阅读11次

    从Spring3.1开始,Spring引入了对Cache的支持。其使用方法和原理都类似于Spring对事务管理的支持。Spring-context包提供了@Cacheable,@CachePut , @CacheEvict,@CacheConfig,@EnableCaching,@Caching等注解,接下来就一一攻破!

    @Cacheable注解

    先点进去看看源码吧

    @Target({ElementType.METHOD, ElementType.TYPE})
    
    @Retention(RetentionPolicy.RUNTIME)
    
    @Inherited
    
    @Documented
    
    public @interface Cacheable {
    
    /**
    
    * 缓存位置名称,不能为空
    
    */
    
    @AliasFor("cacheNames")
    
    String[] value() default {};
    
    /**
    
    * 存储方法调用结果的缓存的名称。名称可用于确定目标缓存(或多个缓存),匹配特定bean定义的限定符值或bean名称。
    
    */
    
    @AliasFor("value")
    
    String[] cacheNames() default {};
    
    /**
    
    * 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合
    
    *
    
    */
    
    String key() default "";
    
    /**
    
    * 自定义key生成策略
    
    */
    
    String keyGenerator() default "";
    
    /**
    
    * 自定义cacheManager
    
    * 与{@link #cacheResolver}属性互斥。
    
    */
    
    String cacheManager() default "";
    
    /**
    
    * 自定义cacheResolver
    
    */
    
    String cacheResolver() default "";
    
    /**
    
    * 触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL
    
    */
    
    String condition() default "";
    
    /**
    
    * 否决缓存条件,支持SpEL
    
    */
    
    String unless() default "";
    
    /**
    
    * 是否支持同步
    
    */
    
    boolean sync() default false;
    
    }
    

    哇!属性还是挺多的,而我们最常用的还是value,key,condition,Spring自带了KeyGenerator()--key生成策略

    public SimpleKey(Object... elements) {
    
    Assert.notNull(elements, "Elements must not be null");
    
    this.params = new Object[elements.length];
    
    System.arraycopy(elements, 0, this.params, 0, elements.length);
    
    this.hashCode = Arrays.deepHashCode(this.params);
    
    }
    

    这就是key的默认生成策略:

    • 如果方法没有参数,则使用0作为key。
    • 如果只有一个参数的话则使用该参数作为key。
    • 如果参数多余一个的话则使用所有参数的hashCode作为key。

    当然也可以自己实现KeyGenerator;

    @Component
    public class CacheKeyGenerator implements KeyGenerator {
    
    @Override
    
    public Object generate(Object target, Method method, Object... params) {
    
    StringBuilder stringBuilder = new StringBuilder();
    
    stringBuilder.append(target.getClass().getCanonicalName());
    
    stringBuilder.append(":");
    
    stringBuilder.append(method.getName());
    
    stringBuilder.append(":");
    
    for (int i = 0; i < params.length; i++) {
    
    stringBuilder.append(params[i]);
    
    if (i < params.length - 1) {
    
    stringBuilder.append(",");
    
    }
    
    }
    
    return stringBuilder.toString();
    
    }
    

    我的就比较简单了,将所有的入参全拼到key中,笔者觉得默认的key生成比较繁琐,且key值可读性也比较查,到不如在key()属性中定义来的简洁明了,上述中多次提到SpEL表达式,到底是何方神圣呢?

    SpEL(Spring Expression Language),即Spring表达式语言,是比JSP的EL更强大的一种表达式语言;是一种可以与一个基于spring的应用程序中的运行时对象交互的东西;是一种简化开发的表达式,通过使用表达式来简化开发,减少一些逻辑、配置的编写。

    这里只贴出key解析的部分代码,想了解更多SpEL表达式可以参考SpEL--Spring表达式语言

    private String parseKey(String key, String fileKey, Method method,Object[] args){
    if (StringUtils.isEmpty(fileKey)) {
    return key;
    }
    //获得被拦截方法参数列表
    LocalVariableTableParameterNameDiscoverer nd = new LocalVariableTableParameterNameDiscoverer();
    String[] parameterNames = nd.getParameterNames(method);
    Expression expression = parser.parseExpression(fileKey);
    EvaluationContext context = new StandardEvaluationContext();
    for(int i = 0 ; i < args.length ; i++) {
    context.setVariable(parameterNames[i], args[i]);
    }
    return key+":"+expression.getValue(context).toString();
    }
    

    解释完了,用起来就简单了

    @Cacheable(value = "names", key = "#id",condition = "id>0",unless = "id<0",keyGenerator = "cacheKeyGenerator")
    

    @CachePut

    用法与@Cacheable相同,区别在于每次调用都会触发更新缓存。

    @CacheEvict

    作用是缓存清除,这里贴出@CacheEvict独有属性

    /**
    
    * 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
    
    */
    
    boolean allEntries() default false;
    
    /**
    
    是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存
    
    */
    
    boolean beforeInvocation() default false;
    

    @CacheConfig

    声明于类上,只要抽象类中方法上@Cacheable的共性,说明白点:所有的@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了,@CacheConfig就干这事。

    @Caching

    有时候我们可能组合多个Cache注解使用;看来代码你就明白了。

    @Caching(put = {
    
    @CachePut(value = "names",key = "#name"),
    
    @CachePut(value = "names",key = "#id")
    
    },cacheable = {
    
    @Cacheable(value = "names",key = "#name"),
    
    @Cacheable(value = "names",key = "#id")
    
    })
    

    当然如果这些注解还满足你的需求,你还可以自定义注解,之前便在项目中用了:

    @Target({ ElementType.METHOD, ElementType.TYPE })
    
    @Retention(RetentionPolicy.RUNTIME)
    
    @Documented
    
    public @interface RedisCache {
    
    //redis分组
    
    String key() default "lianhua";
    
    //key支持spel表达式
    
    String filekey() default "";
    
    //返回类型
    
    Class type();
    
    //是否刷新
    
    boolean reSet() default false;
    
    //默认缓存时间是一天
    
    long expire() default 60*60*24L;
    
    }
    

    最后附上码云上的小demo,欢迎star。

    相关文章

      网友评论

        本文标题:Spring自带整合redis缓存注解

        本文链接:https://www.haomeiwen.com/subject/bxzxhqtx.html