SpringBoot默认缓存配置案例及原理
一、搭建基本环境
1)、创建表
2)、创建javaBean封装数据
package com.zhq.springboot.bean;
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender; //性别 1男 0女
private Integer dId;
public Employee() {
super();
}
public Employee(Integer id, String lastName, String email, Integer gender, Integer dId) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.dId = dId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getdId() {
return dId;
}
public void setdId(Integer dId) {
this.dId = dId;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + ", dId="
+ dId + "]";
}
}
3)、整合MyBatis操作数据库
配置数据源:
@MapperScan指定需要扫描的mapper接口所在的包 :
二、快速体验缓存案例
1)、编写Mapper接口
public interface EmployeeMapper {
@Select("select * from employee where id=#{id}")
public Employee getEmpById(Integer id);
}
2)、编写Service
@Service
public class EmployeeService {
@Autowired
EmployeeMapper employeeMapper;
/**
* 将方法的运行结果进行缓存:以后再要相同的数据,直接从缓存中获取,不用调用方法
* CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;
* 几个属性:
* cacheNames/value:指定缓存组件的名字;
* key缓存数据时使用的key,可以用它来指定,默认是使用方法参数的值 eg:1-方法的返回值
* 可编写SpEL表达式,eg:
* #id表示参数id的值 相当于#a0 #p0 #root.args[0]
* keyGenerator:key的生成器;可以自己指定key的生成器的组件id
* keyGenerator/key:二选一,用其中一个就行
* cacheManager:指定缓存管理器,或者指定缓存解析器cacheResolver
* condition:指定符合条件的情况下才缓存
* unless:否定缓存,当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果集进行判断
* eg:unless="#result==null"
* sync:是否使用异步模式
*
* @param id
* @return
*/
@Cacheable(cacheNames = "emp",key = "#id",condition = "#id>0")
public Employee getEmp(Integer id){
System.out.println("查询"+id+"号员工");
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
}
3)、编写controller
@RestController
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@GetMapping("/emp/{id}")
public Employee getEmp(@PathVariable("id") Integer id){
Employee emp = employeeService.getEmp(id);
return emp;
}
}
4)、测试效果
多次查询id=2会发现数据库只查询了一次,其他的都是从缓存获取的结果
三、缓存实现原理
将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法,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
默认SimpleCacheConfiguration生效
3)、给容器中注册了一个CacheManager:ConcurrentMapCacheManager;
4)、获取和创建ConcurrentMapCache类型的缓存组件,他的作用将数据保存在ConcurrentMap中;
5)、 运行流程:
方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取,(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建;
去Cache中查找缓存的内容,使用一个key,默认就是方法的参数,key是按照某种策略生成的,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key,SimpleKeyGenerator生成key的默认策略:如果没有参数:key=new SimpleKey();如果有一个参数:key=参数的值;如果有多个参数:key=new SimpleKey(params);
没有查到缓存就调用目标方法,将目标方法返回的结果,放进缓存中,@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法并将结果放入缓存,以后再来调用就可以直接使用缓存中的数据。