Spring自带整合Redis缓存注解

从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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354