Spring Cache 总结

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
@Configuration
public class SpringCacheConfig implements ApplicationContextAware {


	private Set<String> cacheNames = new HashSet<>();

	private static final String SEPARATOR = "#";

	@Bean
	public 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会被提前实例化,这个方法会优先执行
	@Override
	public 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 (开启缓存功能)

开启缓存,缓存才能生效
直接启动类上开启
在这里插入图片描述


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

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

拥有属性:

属性名解释
value缓存名,必填,它指定了你的缓存存放在哪块命名空间(就是文件夹名),可多个
cacheNames与 value 差不多,二选一即可
key可选属性,可以使用 SpringEL 标签自定义缓存的key
keyGeneratorkey的生成器。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'")

在这里插入图片描述


3、使用参数作为key

key = "#name"
在这里插入图片描述
此时的key就是code的值

或者拼接字符串

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

在这里插入图片描述


4、使用实体类里的参数
key = "#user.username"
在这里插入图片描述

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 =”方法名“

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

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

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

拥有属性:

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

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

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

拥有属性:

属性名解释
value缓存名,必填,它指定了你的缓存存放在哪块命名空间(就是文件夹名),可多个
cacheNames与 value 差不多,二选一即可
key可选属性,可以使用 SpringEL 标签自定义缓存的key
keyGeneratorkey的生成器。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 差不多,二选一即可
keyGeneratorkey的生成器。key/keyGenerator二选一使用
cacheManager指定缓存管理器
cacheResolver指定获取解析器
在这里插入图片描述
@CacheConfig(cacheNames = {"cacheName"})
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringCacheSpring框架中用于缓存数据的一个功能模块。在Spring 3.1版本之后,Spring引入了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术,并且支持使用JCache(JSR-107)注解来简化开发。 SpringCache支持多种类型的缓存,可以轻松地与SpringBoot集成,只需引入spring-boot-starter-cache依赖即可。 在使用SpringCache时,可以使用自动配置或手动配置来配置缓存管理器。自动配置可以通过RedisCacheConfiguration类来自动配好缓存管理器,配置示例如下: ```java @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) { RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(determineConfiguration(resourceLoader.getClassLoader())); List<String> cacheNames = this.cacheProperties.getCacheNames(); if (!cacheNames.isEmpty()) { builder.initialCacheNames(new LinkedHashSet<>(cacheNames)); } return this.customizerInvoker.customize(builder.build()); } ``` 总结起来,SpringCache是一个用于缓存数据的功能模块,可以方便地与Spring框架和SpringBoot集成,并提供了自动配置和手动配置两种方式来配置缓存管理器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SpringCache](https://blog.csdn.net/weixin_47409774/article/details/123546325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值