spring cache
spring 提供了cache的封装
需要引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.9.RELEASE</version>
</dependency>
根据项目需要 可以设置cache 的具体实现,有如下类型
public enum CacheType {
/**
* Generic caching using 'Cache' beans from the context.
*/
GENERIC,
/**
* JCache (JSR-107) backed caching.
*/
JCACHE,
/**
* EhCache backed caching.
*/
EHCACHE,
/**
* Hazelcast backed caching.
*/
HAZELCAST,
/**
* Infinispan backed caching.
*/
INFINISPAN,
/**
* Couchbase backed caching.
*/
COUCHBASE,
/**
* Redis backed caching.
*/
REDIS,
/**
* Caffeine backed caching.
*/
CAFFEINE,
/**
* Simple in-memory caching.
*/
SIMPLE,
/**
* No caching.
*/
NONE
}
学习掌握的重点集中在redis 和CAFFEINE
redis 是分布式系统必不可少的缓存上实现方式,spring cache 的封装逻辑可以满足大部分如
配置文件、数据字典的缓存逻辑, 避免 数据库访问,或者程序直接的调用
redis的重点是提供分布式的缓存 机制,缓存超时,但是内存回收则是redis 服务自己控制
caffeine 组件则是提供了更加丰富的内存回收控制机制。
spring cache redis 实现
网上大部分资料都需要自己实现
CacheManager
@Bean
public CacheManager cacheManager(RedisConnectionFactory lettuceConnectionFactory) {
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存管理器管理的缓存的默认过期时间
defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(defaultExpireTime))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
Set<String> cacheNames = new HashSet<>();
cacheNames.add(userCacheName);
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put(userCacheName, defaultCacheConfig.entryTtl(Duration.ofSeconds(userCacheExpireTime)));
configMap.put("users", defaultCacheConfig.entryTtl(Duration.ofSeconds(400)));
RedisCacheManager cacheManager = RedisCacheManager.builder(lettuceConnectionFactory)
.cacheDefaults(defaultCacheConfig)
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
KeyGenerator
@Bean
public KeyGenerator keyGenerator() {
/**
* target: 类
* method: 方法
* params: 方法参数
*/
return (target, method, params) -> {
//获取代理对象的最终目标对象
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName()).append(":");
sb.append(method.getName()).append(":");
//调用SimpleKey的key生成器
Object key = SimpleKeyGenerator.generateKey(params);
return sb.append(key);
};
另外有人开源了自定义的
public interface Cache
逻辑,实现了一级缓存使用 caffeine 在服务的内存中,二级缓存在redis 中共享,平衡了内存资源的使用
参考源码:https://github.com/xiaolyuh/layering-cache
反例是一种在service 中实现的缓存逻辑
反例可以实现功能但是 封装的不够优雅,代码复用性不佳
https://blog.csdn.net/Weixiaohuai/article/details/121314530
配置文件
配置文件:
spring:
cache:
redis:
key-prefix: "sp:"
time-to-live: 800
type: redis
注意需要增加一个注解 才能使配置文件生效
@CacheConfig(cacheNames = "users")
public class UserService {....}