从注解的名字就可以看出该注解是一个缓存相关的注解, 在不引入分布式缓存(redis等)的前提下, spring 会默认提供一个缓存(本地缓存 CacheManager)提供使用.
缓存的应用场景
高频词汇, 热点信息, 变化不大等等....的数据, 避免频繁的访问数据库
相关注解
@Cacheable 主要是针对方法的配置,能够根据方法的求情参数对其结果进行缓存。
@CachePut 保证方法被调用,又希望结果被缓存 缓存更新
@CacheEvict 清空缓存 删除数据时的方法。
@EnableCaching 开启基于注解的缓存
使用方法
这里为了节省时间 只讲解@Cacheable的使用, 其他更新删除大同小异
测试
首先查询一个缓存中没有的数据, 缓存中没有所以去查数据库, 并把结果存到缓存中
再次查询这个code值时, 就会发现直接查询缓存了.
比起以往的先查缓存, 如果没有再查数据库是不是优雅的多了.
当然spring底层实现也是如此, 借用aop的原理, 在执行方法前进行相应的操作
参数介绍
cacheNames: 缓存的key的目录名 key: key 名 支持三元表达式 unless: 什么条件下不缓存, 如上图当结果的结果为0时不缓存 condition: 什么时候缓存, 与unless相反 syns:缓存是否使用异步模式 cachemanager:指定缓存管理器
失效时间问题
spring并没有单独为Cacheable指定失效时间的设置, 我们可以对CacheManager进行配置, 达到我们想要的效果.
可以自定义一个cacheManager, 如下图的RedisCacheManager
该构造方法需要3个参数, 分别是
cacheWriter : 需要一个缓存写入器
defaultCacheConfiguration: 默认的失效配置, 理解为默认的配置及失效时间
initialCacheConfigurations: 可以自定义缓存配置
我的redis 缓存相关 具体配置文件, 如下, 可直接拷贝使用
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
return new RedisCacheManager(
RedisCacheWriter.lockingRedisCacheWriter(factory),
this.getRedisCacheConfigurationWithTtl(1),
this.getRedisCacheConfigurationMap()
);
}
/**
* 默认失效时间配置
*
* @param days 未设置失效事件的key 默认days失效
*/
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer days) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofDays(days));
}
public static final String REGION_LIST_BY_CODE_CACHE_KEY = "region:list";
public static final String REGION_NAME_BY_CODE_CACHE_KEY = "region:name";
/**
* 已知缓存名称的映射以及用于这些缓存的配置
*/
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
// 自定义缓存名称对应的配置
redisCacheConfigurationMap.put(REGION_LIST_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(5));
redisCacheConfigurationMap.put(REGION_NAME_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(10));
return redisCacheConfigurationMap;
}