> 文档中心 > Spring Cache 总结

Spring Cache 总结

SpringCache

  • 1、配置
  • 2、注解
    • `@EnableCaching` (开启缓存功能)
    • `@Cacheable` (将数据保存到缓存)
      • 1、key参数设置,SpringEl表达式
      • 2、其他参数示例
    • `@CacheEvict` (将数据从缓存删除)
    • `@CachePut ` (不影响方法执行更新缓存)
    • `@Caching` (组合多个缓存操作)
    • `@CacheConfig` (在类级别共享缓存的相同配置)

1、配置

1、依赖

<!--springcache依赖-->   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>   </dependency>   <!--使用redis作为缓存-->   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>   </dependency>

2、yml配置

spring:  cache:    type: redis #指定缓存类型为redis # redis配置  redis:    host: localhost    port: 6379    database: 2    jedis:      pool: max-active: -1 max-wait: 3000ms    timeout: 3000ms

3、cache配置

package com.example.demo.config;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.serializer.StringRedisSerializer;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.beans.factory.support.AbstractBeanDefinition;import org.springframework.cache.CacheManager;import org.springframework.cache.interceptor.CacheOperation;import org.springframework.cache.interceptor.CacheOperationSource;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;import org.springframework.util.*;import java.time.Duration;import java.util.*;@EnableCaching@Configurationpublic class SpringCacheConfig implements ApplicationContextAware {private Set<String> cacheNames = new HashSet<>();private static final String SEPARATOR = "#";@Beanpublic CacheManager cacheManager(RedisConnectionFactory connectionFactory) {//默认过期时间2天RedisCacheConfiguration defaultConfiguration = getRedisCacheConfigurationWithTtl(2 * 24 * 3600);RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.builder(connectionFactory).cacheDefaults(defaultConfiguration);if (!CollectionUtils.isEmpty(cacheNames)) {Map<String, RedisCacheConfiguration> cacheConfigurations = new LinkedHashMap<>();for (String cacheName : cacheNames) {if (cacheName.contains(SEPARATOR)) {String[] strs = StringUtils.split(cacheName, SEPARATOR);Assert.notNull(strs);long ttl = Long.parseLong(strs[1].trim());RedisCacheConfiguration customizedConfiguration = getRedisCacheConfigurationWithTtl(ttl);cacheConfigurations.put(cacheName, customizedConfiguration);}}if (cacheConfigurations.size() > 0) {builder.withInitialCacheConfigurations(cacheConfigurations);}}return builder.build();}private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(long ttl) {return RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())).entryTtl(Duration.ofSeconds(ttl));}//实现ApplicationContextAware接口的Bean会被提前实例化,这个方法会优先执行@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (!(applicationContext instanceof ConfigurableApplicationContext)) {return;}ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;//CacheOperationSource 可以被提前实例化,是spring cache提供的工具类CacheOperationSource cacheOperationSource = context.getBean(CacheOperationSource.class);ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();for (String beanName : beanFactory.getBeanDefinitionNames()) {AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(beanName);try {Class<?> beanClass = beanDefinition.resolveBeanClass(ClassUtils.getDefaultClassLoader());if (beanClass != null) {ReflectionUtils.doWithMethods(beanClass, m -> {Collection<CacheOperation> cacheOperations = cacheOperationSource.getCacheOperations(m, beanClass);if (!CollectionUtils.isEmpty(cacheOperations)) {for (CacheOperation operation : cacheOperations) {cacheNames.addAll(operation.getCacheNames());}}});}} catch (ClassNotFoundException e) {e.printStackTrace();}}}}

2、注解

@EnableCaching (开启缓存功能)

开启缓存,缓存才能生效
直接启动类上开启
Spring Cache 总结


@Cacheable (将数据保存到缓存)

根据方法返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

拥有属性

属性名 解释
value 缓存名,必填,它指定了你的缓存存放在哪块命名空间(就是文件夹名),可多个
cacheNames 与 value 差不多,二选一即可
key 可选属性,可以使用 SpringEL 标签自定义缓存的key
keyGenerator key的生成器。key/keyGenerator二选一使用
cacheManager 指定缓存管理器
cacheResolver 指定获取解析器
condition 条件符合则缓存
unless 条件符合则不缓存
sync 是否使用异步模式,默认为false

1、key参数设置,SpringEl表达式

测试
1、默认方法
在这里插入图片描述

默认方法解析:

  • 如果缓存中有,方法不用调用
  • key默认自动生成,缓存名字::SimpleKey []

在这里插入图片描述
value就是方法的返回值


2、指定简单key
key = "'cacheableKey'"

指定key,默认是spEL表达式,所以字符串需要用单引号

@Cacheable(value = {"cacheable1","cacheable2"},key = "'cacheableKey'")

Spring Cache 总结


3、使用参数作为key

key = "#name"
Spring Cache 总结
此时的key就是code的值

或者拼接字符串

// 或者拼接一下@Cacheable(value = {"cacheable1"},key = "#name + ':' + #code")

Spring Cache 总结


4、使用实体类里的参数
key = "#user.username"
Spring Cache 总结

5、更多key方法

属性名称 描述 示例
methodName 当前方法名 #root.methodName
method 当前方法 #root.method.name
target 当前被调用的对象 #root.target
targetClass 当前被调用的对象的class #root.targetClass
args 当前方法的参数,如取第一个参数就是args[0] #root.args[0]
caches 当前被调用的方法使用的cache #root.caches[0].name

2、其他参数示例

cacheNames和value作用一样,分区(文件夹)

@Cacheable(cacheNames = {"cacheable1"},key = "#user")

unless条件符合不缓存, 如下:结果是null,不用缓存

@Cacheable(value = {"cacheable1"},key = "#code",unless = "#result == null" )

condition条件符合缓存, 如下:参数user的长度大于2,可以缓存

@Cacheable(value = {"cacheable1"},key = "#user",condition = "#user.length() > 2")

keyGenerator 生成key

@Cacheable(cacheNames = {"cacheable1"},keyGenerator ="keyGenerator" )

这个需要自己写生成的算法,keyGenerator =”方法名“

@Componentpublic class keyGenerator implements KeyGenerator {@Overridepublic Object generate(Object o, Method method, Object... objects) {// 这里写你的key生成的算法return "123";}}

@CacheEvict (将数据从缓存删除)

使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上

拥有属性:

属性名 解释
value 缓存名,必填,它指定了你的缓存存放在哪块命名空间(就是文件夹名),可多个
cacheNames 与 value 差不多,二选一即可
key 可选属性,可以使用 SpringEL 标签自定义缓存的key
keyGenerator key的生成器。key/keyGenerator二选一使用
cacheManager 指定缓存管理器
cacheResolver 指定获取解析器
condition 条件符合则缓存
allEntries 是否清空所有缓存,默认为false。如果指定为true,则方法调用后将立即清空所有缓存
beforeInvocation 是否在方法执行前就清空,默认为false。如果指定为true,则在方法执行前就会清空缓存
@CacheEvict(value = {"cacheable1"},key ="'123'",allEntries = true,beforeInvocation = true)

@CachePut (不影响方法执行更新缓存)

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中,会更新缓存的值。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。

拥有属性:

属性名 解释
value 缓存名,必填,它指定了你的缓存存放在哪块命名空间(就是文件夹名),可多个
cacheNames 与 value 差不多,二选一即可
key 可选属性,可以使用 SpringEL 标签自定义缓存的key
keyGenerator key的生成器。key/keyGenerator二选一使用
cacheManager 指定缓存管理器
cacheResolver 指定获取解析器
condition 条件符合则缓存
unless 条件符合则不缓存
@CachePut(value = {"cacheable1"},key ="'123'")

@Caching (组合多个缓存操作)

该注解可以实现同一个方法上同时使用多种注解。各属性值可以多个,如删除多个key

拥有属性:

属性名 解释
evict 对应删除操作的注解
cacheable 对应存储缓存操作的注解
put 对应更新缓存操作的注解
@Caching(evict = {@CacheEvict(value = "caching",key = "'123'"),@CacheEvict(value = "caching2",key = "'321'")},cacheable = @Cacheable(value = "caching",key = "'123'"),put = @CachePut(value = "caching2",key = "'321'"))

@CacheConfig (在类级别共享缓存的相同配置)

当我们需要缓存的地方越来越多,你可以使用@CacheConfig(cacheNames = {“cacheName”})注解在 class 之上来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。

拥有属性:

属性名 解释
cacheNames 与 value 差不多,二选一即可
keyGenerator key的生成器。key/keyGenerator二选一使用
cacheManager 指定缓存管理器
cacheResolver 指定获取解析器

在这里插入图片描述

@CacheConfig(cacheNames = {"cacheName"})