一、JSR107缓存标准规范:
Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry和Expiry。
- .CachingProvider定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
- .CacheManager定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
- .Cache是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
- .Entry是一个存储在Cache中的key-value对。
- .Expiry每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置

二、Spring缓存

注:@CachePut用于方法更新,该注解标注的方法每次都会别调用,且结果被缓存
三、快速使用缓存:
1、开启基于注解缓存@EnableCaching
2、标注缓存注解即可
@Cacheable
@CacheEvict
@CachePut
/** * CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字; * 几个属性: * cacheNames/value:指定缓存组件的名字 * key:缓存数据使用的key,可以用它来指定。默认是使用方法参数的值 * 可以编写spel来指定 如:#id;参数id的值 等同于#a0 #p0 #root.args[0] * keyGenerator: key的生成器;可以自己指定key的生成器的组件 如:key="#root.methodName+'['+#id+']'"(key为getArticleById[33]) * key/keyGenerator二选一使用 * cacheManager:指定缓存管理器:或者cacheResolver指定 二选一 * condition:指定符合条件的情况下才缓存;
如:condition="#id>0" 参数id值大于0才进行缓存
或: condition="#id>0 and #root.methodName eq 'aaa'" * unless:否定缓存:当unless指定条件为true,方法的缓存值就不会缓存;可以获取到结果进行判断 * sync:是否使用异步模式 * @param id * @return */ @Cacheable(cacheNames = "article") public Article getArticleById(Integer id) { System.out.println("当前查询getArticleById:" + id); return articleMapper.getArticleById(id); }
缓存可用的el表达式


四、缓存原理:
缓存自动配置类CacheAutoConfiguration
缓存导入的配置类:
0 = "org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration"
1 = "org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration"
2 = "org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration"
3 = "org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration"
4 = "org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration"
5 = "org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration"
6 = "org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration"
7 = "org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration"
8 = "org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration"
9 = "org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration"
10 = "org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration"
默认:SimpleCacheConfiguration生效,给容器中注册了一个cacheManager:ConcurrentMapCacheManager,可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在concurrentMap中;
核心:
1)使用cacheManager【ConcurrentMapCacheManager】按照名字得到cache【ConcurrentMapCache】
2)key使用keyGenerator生成的,默认是SimpleKeyGenerator
五、@CachePut :调用方法,同时更新缓存
1、与@Cacheable区别:运行时机不一样:@CachePut 先调目标方法,然后缓存结果。@Cacheable先判断是否有该name的cache,没有则创建,再根据key判断缓存中是否有此数据,没有调用目标方法缓存结果,有则直接从缓存中取
2、@CachePut要注意更新缓存时,key要与查询缓存时的key一致,否则不能达到目的 ,另外要注意方法返回结果要和查询结果一样,即value要一样
例:
@CachePut(value = "article", key="#article.id")
public Article updateArticleById(Article article) {
System.out.println("article更新成功:" + article.getId());
articleMapper.updateArticle(article);
return article;
}
六、@CacheEvict:缓存删除
key:指定要清除的数据
allEntries=true:指定清除这个缓存中所有的数据
beforeInvocation=false:缓存清除是否在方法之前执行
默认缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除
beforeInvocation=true:
代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
例:
@CacheEvict(value = "article", allEntries=true) public void deleteById(Integer id) { System.out.println("删除article:" + id); // articleMapper.deleteArticleById(id); }
七、@Caching 与@CacheConfig
@Caching定义复杂的缓存规则,实际上是@Cacheable、@CachePut、@CacheEvict的组合注解
@CacheConfig标注在类上,定义公共的缓存属性
八、整合redis
使用:引入spring-boot-starter-data-redis依赖,配置reids连接yml,注入spring自动配置生成的RedisTemplate(为方便序列化可自定义)
/** * Redis常见五大数据类型 * String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合) * redisTemplate.opsForValue() * redisTemplate.opsForList() * redisTemplate.opsForSet() * redisTemplate.opsForHash() * redisTemplate.opsForZSet() * @param id * @return */ @RequestMapping("/query/{id}") public Article queryArticle(@PathVariable("id") Integer id) { Article article = articleService.getArticleById(id); redisTemplate.opsForValue().set("queryArticle" + id, article); return article; }
@Configuration public class RedisConfig { @Bean public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(jackson2JsonRedisSerializer); return template; } }
原理:CacheManager===Cache缓存组件来实际给缓存中存取数据
1)、引入redis的starter,容器中保存的是RedisCacheManager:
2)、RedisCacheManager帮我们创建RedisCache来作为缓存组件:
3)、默认保存数据k-v都是object,利用序列化保存;(原因:默认创建的RedisCacheManager操作数据时是使用的RedisTemplate,RedisTemplate默认使用的jdk序列化机制)
4)、自定义CacheManager(默认RedisCacheManager会将cacheName作为key的前缀)