SpringBoot使用Spring缓存注解

SpringBoot使用Spring缓存注解

声明:Spring缓存注解的使用非常简单,主要是理解,所以本文主要以示例+注释(图片版)进行说明,核心部分 会给出文字版;当然本人测试时完整的项目代码会放在GitHub上,链接见本文末。

目录

启用Spring缓存注解技术

Spring缓存注解总体介绍

缓存注解的常用属性(以示例进行说明)

key

condition

cacheNames

unless

allEntries

beforeInvocation

缓存注解使用在返回值为viod方法上的测试

背景简述: 自Spring3.1开始,Spring就自带了对缓存的支持。我们可以直接使用Spring缓存技术将某些数据放入本机的缓存中;Spring缓存技术也可以搭配其他缓存中间件(如Redis等)进行使用,将某些数据写入到缓存中间件(缓存中间件可能在其他机器上)中。

启用Spring缓存注解技术:

第一步:确认Spring版本不低于3.1。

注:本人用的是SpringBoot2.1.2.RELEASE,对应的Spring版本为5.1.4.RELEASE。

第二步:在SpringBoot启动类上启用Spring缓存技术。

第三步:在类上或类中的方法上使用缓存注解。

注:这个【类】指的是注入了Spring容器中的。如果没有注入,那么在该类上或该类中的缓存注解是不会生效的。

Spring缓存注解总体介绍:

Spring提供的缓存注解有:

常用的注解有:@EnableCaching、@Cacheable、@CacheEvict、@CachePut、@Caching、@CacheConfig。

提示:本部分提到的key,可见本文下面关于缓存注解各属性的介绍。

@EnableCaching:开关性注解,在项目启动类或某个配置类上使用此注解后,则表示允许使用注解的方式进行缓存操作,如:

@Cacheable:可用于类或方法上;在目标方法执行前,会根据key先去缓存中查询看是否有数据,有就直接 返回缓存中的key对应的value值。不再执行目标方法;无则执行目标方法,并将方法的返回值 作为value,并以键值对的形式存入缓存,如:

@CachePut:可用于类或方法上;在执行完目标方法后,并将方法的返回值作为value,并以键值对的形式存入缓存中,如:

@CacheEvict:可用于类或方法上;在执行完目标方法后,清除缓存中对应key的数据(如果缓存 中有对应key的数据缓存的话),如:

@Caching:此注解即可作为@Cacheable、@CacheEvict、@CachePut三种注解中的的任何一种或几种来使用,如:

@CacheConfig:@Cacheable、@CacheEvict、@CachePut这三个注解的cacheNames属性是必 填项(或value属性是必填项,因为value属性是cacheNames的别名属性);如果上述 三种注解都用的是同一个cacheNames的话,那么在每此都写cacheNames的话, 就会显得麻烦。如将@CacheConfig注解就是来配置一些公共属性(如:cacheNames、 keyGenerator等)的值的,如:

缓存注解的常用属性(以示例进行说明):

key:

key的来源可分为三类,分别是:默认的、keyGenerator生成的、主动指定的。

下面在具体代码中进行说明,注意阅读注释说明!

默认key:

keyGenerator生成key:

编写配置类、定制化key生成器:

import org.springframework.cache.annotation.CachingConfigurerSupport;

import org.springframework.cache.interceptor.KeyGenerator;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**

* 定制化CachingConfigurer

*

* @author JustryDeng

* @date 2019/4/11 16:26

*/

@Configuration

public class MyCachingConfigurer extends CachingConfigurerSupport {

/**

* 定制化key生成器

*

* 设置 全限定类名 + 方法名 + 参数名 共同组成 key

*

* @return key生成器

* @date 2019/4/12 14:09

*/

@Bean

@Override

public KeyGenerator keyGenerator() {

return (Object target, Method method, Object... params) -> {

StringBuilder sb = new StringBuilder(16);

sb.append(target.getClass().getName());

sb.append("_");

sb.append(method.getName());

sb.append("_");

for (int i = 0; i < params.length; i++) {

sb.append(params[i]);

if (i < params.length - 1) {

sb.append(",");

}

}

return sb.toString();

};

}

}

此时,若使用缓存注解时不指定key属性,那么就会默认采用Key生成器生成的注解:

主动指定key:

condition:

在激活注解功能前,进行condition验证,如果condition结果为true,则表明验证通过,缓存注解生效;否则缓存注解不生效。

condition作用时机在:缓存注解检查缓存中是否有对应的key-value 之前。 注:缓存注解检查缓存中是否有对应的key-value 在 运行目标方法之前, 所以 condition作用时机也在运行目标方法之前。

实验示例:

验证:

cacheNames:

通过cacheNames对数据进行隔离,不同cacheName下可以有相同的key。也可称呼cacheName为命名空间。实际上(以spring-cache为例),可以通过设置RedisCacheConfiguration#usePrefix的true或false来控制是否使用前缀。如果否,那么最终的redis键就是key值;如果是,那么就会根据cacheName生成一个前缀,然后再追加上key作为最终的redis键.cacheName还有其它重要的功能:cacheName(就像其名称【命名空间】所说)实现了数据分区的功能,一些操作可以直接按照命名空间批量进行。如:spring框架中的Cache实际对应的就是一个【命名空间】,spring会先去找到数据所在的命名空间(即:先找到对应的Cache),再由Cache结合key,最终定位到数据。

下面验证的是:当同时指定多个cacheName时,从哪一个cacheName取数据。

这里先给出结论:

若属性cacheNames(或属性value)指定了多个命名空间;

当进行缓存存储时,会在这些命名空间下都存一份key-value。

当进行缓存读取时,会按照cacheNames值里命名空间的顺序,挨个挨个从命名空间中查找对应的key,如果在某个命名空间中查找打了对应的缓存,就不会再查找排在后面的命名空间,也不会再执行对应方法,直接返回缓存中的value值。

实验示例:

验证:

unless:

功能是:是否令注解(在方法执行后的功能)不生效;若unless的结果为true,则(方法执行后的功能)不生效;若unless的结果为false,则(方法执行后的)功能生效。

注:unless默认为"",即相当于默认为false。

unless的作用时机:目标方法运行后。 注:如果(因为直接从缓存中获取到了数据,而导致)目标方法没有被执行,那么unless字段不生效。

举例说明一: 对于@Cacheable注解,在执行目标方法前,如果从缓存中查询到了数据,那么直接返回缓存中的数据;如果从 缓存中没有查询到数据,那么执行目标方法,目标方法执行完毕之后,判断unless的结果,若unless的结果为true,那么不缓存方法的返回值;若unless的结果为false,那么缓存方法的返回值。

举例说明二: 对于@CachePut注解,在目标方法执行完毕之后,判断unless的结果,若unless的结果为true,那么不缓存方法的返回值;若unless的结果为false,那么缓存方法的返回值。

注:因为unless的作用时机是在方法运行完毕后,所以我们可以用SpEL表达式#result 来获取方法的返回值。

实验示例:

验证:

说明:本人跑了几次此测试方法,每次随机产生的key(从代码里面可知,本人已入参参数为key)都是之前缓存 里面没有的,也就是说每次都会执行目标方法;发现大于等于5000的随机数都存入缓存汇总了;而小 于5000的随机数则没有。

allEntries:

此属性主要出现在@CacheEvict注解中,表示是否清除指定命名空间中的所有数据,默认为false。

beforeInvocation:

此属性主要出现在@CacheEvict注解中,表示 是否在目标方法执行前使 此注解生效。 默认为false,即:目标方法执行完毕后此注解生效。

缓存注解使用在返回值为viod方法上的测试:

结论是:缓存注解作用于void方法上,仍然会向缓存中进行存储,不过键值对中的value为null。

实验示例:

验证:

笔者寄语:

关于Spring缓存注解的其他一些属性、用法等这里就不再一一叙述了,感兴趣的可自行查询相关资料或阅读源码进行测试。

^_^ 如有不当之处,欢迎指正

^_^ 测试代码托管链接 https://github.com/JustryDeng/CommonRepository

^_^ 本文已经被收录进《程序员成长笔记(二)》,笔者JustryDeng

相关推荐

国学大师、资本大佬、商业巨头都来了!厉害了李强365!
《魔兽世界》凄凉之地人马声望崇拜攻略
365直播网APP下载

《魔兽世界》凄凉之地人马声望崇拜攻略

09-08 👁️ 9095
《云顶之弈》S12魔战卡萨丁阵容玩法攻略推荐
365bet亚洲官网

《云顶之弈》S12魔战卡萨丁阵容玩法攻略推荐

08-03 👁️ 7343