【SpringBoot】④SpringBoot与缓存

实际2020-04-30 10:23:47
此篇文章使用版本:2.2.2.RELEASE
源码

入门

案例

1
2
3
4
5
6
7
8
9
spring.datasource.url=jdbc:mysql://192.168.1.1:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
#注释掉也不影响,会根据jar包自动注入mysql驱动
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#开启驼峰命名法 数据库自动ab_cd会对应实体类属性abCd
#mybatis.configuration.map-underscore-to-camel-case=true
#将 tpf.mapper 下的所有SQL语句日志打印出来
logging.level.tpf.mapper=debug

在这里插入图片描述

@EnableCaching

开启基于注解的缓存
在这里插入图片描述

1
2
@Import({CachingConfigurationSelector.class})
导入CachingConfigurationSelector组件,这个组件会导入一些关于缓存的自动配置,后面我们会分析到。

@Cacheable

添加缓存:将方法的运行结果进行缓存,以后要相同的数据,直接从缓存中获取,不用调用方法了
调用时机:先看缓存是否有,没有就调用方法并放入缓存;如果有,直接返回缓存中的数据。
注意:@Cacheable不能使用key中包含result,因为它是先判断key再调用方法【例如:key = “#result”是错误的】
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存;
例如:cacheNames = "student" 或者 cacheNames = {"student","student01"}
【CacheManager管理多个Cache组件,对缓存的真正增删改查是操作在Cache组件中的,每一个缓存组件有自己唯一一个名字】

key:指定缓存数据使用的key;可以用它来指定。默认是使用方法参数的值【key=id,value=方法的返回值】
例如 selectStudentById()方法传入1,则key为1,value为返回的Student对象
支持SpEL表达式 key="#root.args[0]" 其中#root.args[0] 可以换成 #p0 #a0 #iban 也可以#参数名,例如 #id
如果传入id为2 想让key为 selectStudentById[2] 可以写成 key = "#root.methodName+'['+#id+']'"
@Cacheable中的key不能用#result,因为@Cacheable是方法调用之前进行缓存,@CachePut是方法调用之后进行缓存

keyGenerator:key的生成器;可以自己指定key的生成器的组件id,使用方式参考下面
key/keyGenerator:二选一使用;【不能同时用】

cacheManager:指定缓存管理器;或 cacheResolver指定获取解析器 【不能同时用】

condition:指定符合条件的情况下才缓存,也可用SpEL表达式;
例如 condition = "#id>0" 表示 传入参数 id 的值大于0才能进行缓存
condition = "#a0>1":第一个参数的值>1的时候才进行缓存

unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;
可以使用#result获取结果进行判断,例如 unless="#result==null" 如果结果为null就不进行缓存
//condition = "#id==3",unless = "#id==3" id为什么都不缓存
//condition = "#id>1",unless = "#id==3" id<=1或id==3不缓存,其他时候都缓存
unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
sync:是否使用异步模式,开启异步不支持unless属性

keyGenerator的使用
keyGenerator的使用
cacheManager的使用请见自定义RedisCacheManager

@CachePut

更新缓存调用时机:直接先调用方法,然后将结果放缓存中。有对应key就进行替换,没有就进行添加。
注意:可以使用key = “#result” 把返回值作为key
在这里插入图片描述

@CacheEvict

在这里插入图片描述

1
2
allEntries:清除指定缓存的所有数据
beforeInvocation:是否在执行方法之前清除缓存,默认否false。设置为true,无论有没有异常都会清除缓存。

@Caching

定义复杂的缓存规则
在这里插入图片描述

@CacheConfig

抽取缓存的公共配置,加在类上,方法中就不用写了。如果类和方法同时写,方法生效。
在这里插入图片描述

原理分析

在这里插入图片描述
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法;
CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;


原理:
1、自动配置类;CacheAutoConfiguration
2、缓存的配置类
org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认生效】
org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
3、哪个配置类默认生效:SimpleCacheConfiguration;

4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager
5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中;

运行流程:
@Cacheable:
1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取;
(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。
2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;
key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key;
SimpleKeyGenerator生成key的默认策略;
如果没有参数;key=new SimpleKey();
如果有一个参数:key=参数的值
如果有多个参数:key=new SimpleKey(params);
3、没有查到缓存就调用目标方法;
4、将目标方法返回的结果,放进缓存中

@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,
如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据;

核心:
1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator

整合Redis

参考Redis【2】五大基本数据类型

简单入门

1
2
#指定Redis地址,Docker启动Redis 192.168.1.1,打开Redis 桌面可视化
spring.redis.host=192.168.1.1

在这里插入图片描述

说明

在SpringBoot2.x之后,原本的Jedis被替换成了Lettuce
Jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用Jedis Pool连接池。更像BIO模式。
Lettuce:采用Netty,实例可用再多个线程中进行共享,不存在线程不安全的情况~!可以减少线程数据,更像NIO模式。
在这里插入图片描述

自定义RedisTemplate

源码

自定义RedisTemplate实现JSON序列化:
除了下面的实现,也可用另一种方式:存入的时候进行对象转JSON,取出再转一次。
在这里插入图片描述

自定义CacheManager

源码

自定义缓存管理器
在这里插入图片描述
在这里插入图片描述

默认序列化

注意:
1)、RedisTemplate是操作Redis的模版,同Jedis一样,可以对Redis进行增删改查等操作,默认K,V都是Object,默认序列化机制是JdkSerializationRedisSerializer
2)、RedisCacheManager是管理缓存管理器的,SpringBoot默认是SimpleCacheConfiguration,此时我们引入了Redis,所以使用的是Redis的缓存管理器,默认存入的V也是使用JdkSerializationRedisSerializer
3)、在上面我们使用了自定义RedisTemplate和自定义CacheManager可以修改序列化机制,使用JSON格式来存储V。
在这里插入图片描述