目录
SpringBoot默认缓存机制
@EnableCaching
@Cacheable
@CachePut
@CacheEvict
@CacheConfig
@Caching
缓存工作原理
SpringBoot默认缓存机制
接下来在前面搭建的Web应用基础上(可以看Springboot缓存学习(一)),开启SpringBoot默认支持的缓存,体验SpringBoot默认缓存的使用效果以及下相关的注解使用;
由于下面的学习需要开启日志打印功能,所以需要在配置文件中作以下配置;
#开启日志打印
logging.level.com.pojo123.springboot=debug
首先看一下不使用SpringBoot缓存机制,进行数据库查询操作
在开启服务后在游览器中输入http://localhost:8080/emp/1,访问三次,查看控制台的输出结果
我们可以看到,后台进行了三次的数据库查询操作,前面我们说到过,多次重复的数据库查询操作会增加数据库的访问压力,所以这里我们可以使用SpringBoot的缓存机制,进行优化
@EnableCaching
使用@EnableCaching注解开启基于注解的的缓存支持,该注解通常会添加在项目的启动类上;
@EnableCaching //开启springboot基于注解的缓存管理支持
@SpringBootApplication
public class Springboot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01CacheApplication.class, args);
}
}
@Cacheable
使用 @Cacheable注解对数据库操作方法进行缓存管理。将@Cacheable注解标注在Service类的查询方法上,对查询结果进行缓存,该注解的执行顺序是,先进行缓存查询,如果为空,则进行方法查询,并将结果进行缓存;如果缓存中有数据,则不进行方法查询,而是直接使用缓存数据;
该注解有多个属性
- cachenames/value:指定缓存组件的名字,将方法的返回值结果放在哪个缓存中,是数组的方式,可以指定 多个缓存。
- key:用key来指定缓存数据的key,可以使用SpEl表达式;
- keyGenerator:key的生成器,可以自己指定key的生成器组件id,和key属性二选一使用
- cacheManager:指定缓存管理器,或者cacheResolver指定获取解析器二者二选一
- condition:执行符合条件的情况下才缓存
- unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存,可以获取到结果进行判断;unless="#result==null"
- sync:是否使用异步缓存,默认为false
这里我们只需要使用它的cachenames属性指定缓存组件的名字,将本次查询的结果放入名为emp的缓存组件中
@Cacheable(cacheNames = {"emp"})
public Employee getEmp(Integer id){
System.out.println("现在开始查询"+id+"号员工信息");
Employee emp = employeeMapper.getEmpbyId(id);
return emp;
}
然后进行测试:
首先输入http://localhost:8080/emp/1 进行查询,并将查询到的数据存入缓存中,以key:value格式存入emp的缓存组件中;控制台上显示一条数据库查询信息
然后清空控制台,再次进行查询,会发现控制台并没有输出,也就是说没有进行数据库查询操作,而是从缓存中取得的数据
以上就是基本的SpringBoot基础的默认缓存机制的体验;接下来会对其其它高级部分的功能及注解原理进行解释说明;
@CachePut
@CachePut注解是由Spring框架提供的,可以用作类或者方法(通常用在数据更新方法上)。该注解的作用是更新缓存数据。该注解的执行顺序是,先进行方法的调用,然后将方法的结果更新到缓存中;
该注解提供了多个属性,这些属性和@Cacheable注解的属性完全相同;
注意:使用该注解时,选择更新的数据的缓存组件的名称和key一定要和查询缓存的组件名称和key相同
用法:
先使用该注解对方法进行注解,这里特别注意要指定key和上面查询缓存的key相同,这样在进行数据更新之后,才能对指定的缓存组件的数据进行更新,查询到的组件也是更新之后的缓存数据;
@CachePut(value = "emp" ,key="#result.id")
public Employee updateEmp(Employee employee){
System.out.println("更新员工信息"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
Controller层:
@GetMapping("/emp")
public Employee update(Employee employee){
Employee emp = employeeService.updateEmp(employee);
return emp;
}
测试步骤
- 查询1号员工,查到的结果放入缓存中
- key:1 value:原来的值
- 以后查询从缓存中取数据,还是以前的结果
- 更新1号员工
- key: 1,value:返回的employee
- 查询1号员工(一号员工更新)
运行结果这里就不再进行张贴,可以自己自行测试;至于上面为什么这样指定key,后面的缓存工作原理部分将会进行说明;
@CacheEvict
@CacheEvict注解也是SpringBoot提供,用作类和方法(通常用在数据删除方法上,该注解的作用是删除缓存数据,该注解的默认执行顺序是,先进行方法的调用,再清除缓存数据);
该注解的属性也和@Cacheable相同,初次之外,还提供了两个特殊的属性allEntries和beforeInvocation;
(1)allEntries=true 指定清除这个缓存中所有的数据
(2)beforeInvocation=false:缓存的清除是否在方法之前执行,默认false是在方法执行之后执行,如果出现异常方法不会被清除;True时在方法执行之前清除缓存,无论方法是否出现异常,都会清除缓存。
@CacheConfig
该注解用于类,用于统筹管理类中使用@Cacheable,@Cacheput,@CacheEvit注解的方法中的公共属性,这些公共属性包括cacheNames,keyGenerator,cacheManager,和cacheResolver,用于统筹设置,简化代码开发;
@Caching
用于处理复杂规则的数据缓存,用于类和方法,@Caching注解包含cacheable,put,evict三个属性,作用等同于上面介绍的三个属性;
缓存工作原理
- 方法运行之前,先去按照cacheNames指定的名字查询Cache(缓存组件),(CacheManger先获取相应的缓存,)第一次获取缓存如果没有Cache组件 会自动创建。
- 去Cache中查找缓存的内容,使用一个key,默认就是方法的参数;key是按照某种策略生成的;默认使用keyGenarator生成的,默认使用SimpleKeyGennarator生成key
- SimpleKeyGenarator生成key的默认策略:
- 如果没有参数key=new SimpleKey();
- 如果有一个参数:key=参数的值
- 如果有多个参数:key=new SimpleKey(params)
- 没有查到缓存就调用目标方法
- 将目标方法返回的结果放入缓存中
核心:
- 使用CacheManager【CoucurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
- key使用keyGenerator生成的,默认是SimpleKeyGennarator