SpringBoot_缓存
缓存的意义:用来加速系统的访问,提升系统的性能;比如系统中高频热点数据的访问;
JSP107:
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缓存抽象:
从Spring 3.1 开始定义了org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术;并支持使用JCache(JSR-107) 注解简化我们开发;
Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;
Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;
使用 @EnableCaching 开启缓存:
@SpringBootApplication
@EnableCaching
public class SpringBoot08CacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot08CacheApplication.class, args);
}
}
工作原理:
缓存的=自动配置类:CacheAutoConfiguration ;
/**
缓存的配置类
* 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 :
@ConditionalOnMissingBean({CacheManager.class})
@Conditional({CacheCondition.class})
class SimpleCacheConfiguration {
SimpleCacheConfiguration() {
}
@Bean
//给容器中注册了CacheManager:ConcurrentMapCacheManager
ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager);
}
}
//调用createConcurrentMapCache方法:创建缓存组件,将数据保存在ConcurrentMap中
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = this.isStoreByValue() ? this.serialization : null;
return new ConcurrentMapCache(name, new ConcurrentHashMap(256), this.isAllowNullValues(), actualSerialization);
}
注解:
@Cacheable注解:
SpEL表达式:
运行流程: @Cacheable 标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行目标方法并将结果放入缓存;后面再调用就可以直接使用缓存中的数据;
方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取; (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建; |
在Cache中通过key查找缓存的内容,key默认就是方法的参数; key是按照某种策略生成的,默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator ; SimpleKeyGenerator生成key的默认策略:如果没有参数:key=new SimpleKey();如果有一个参数:key= param(参数的值);如果有多个参数:key=new SimpleKey(params); |
没有查到缓存就调用目标方法; |
将目标方法返回的结果通过put方法放进缓存中; |
示例:
@Cacheable(value="emp",
key = "#root.methodName+'['+#id+']'",/*自定义指定key,默认是使用方法参数的值*/
keyGenerator = "myKeyGenerator",/*调用自定义keyGenerator生成key */
condition = "#a0>1", /*当 符合条件的情况下才缓存*/
unless = "#a0==2" /* 当unless指定的条件为true,方法的返回值就不会被缓存 */)
public Employee getEmp(Integer id){
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
@CachePut注解:同步更新缓存
运行流程: @CachePut 标注的方法会先调用目标方法,再将结果放入缓存中;@CachePut标注方法的目标方法一定会执行;
/**
* 测试步骤:
* 1、查询1号员工;查到的结果会放在缓存中;
* key:1 value:lastName:张三
* 2、以后查询还是之前的结果
* 3、更新1号员工;【lastName:zhangsan;gender:0】
* 将方法的返回值也放进缓存了;
* key:传入的employee对象 值:返回的employee对象;
* 4、查询1号员工 :应该是更新后的员工;
* key = "#employee.id":使用传入的参数的员工id;
* key = "#result.id":使用返回后的id,但是@Cacheable的key是不能用#result,因为@Cacheable是在目标方法执行之前运行
*/
@CachePut(value = "emp",
key = "#result.id" /*取缓存和放入缓存的key保持一致*/)
public Employee updateEmp(Employee employee){
employeeMapper.updateEmp(employee);
return employee;
}
@CacheEvict注解:缓存清除
@CacheEvict(value="emp",key = "#id",
allEntries = true,/*指定清除这个缓存中所有的数据*/
/**
*beforeInvocation:默认等于false;
*beforeInvocation = false:缓存的清除是在方法运行之后执行, 如果出现异常缓存就不会清除;
*beforeInvocation = true: 缓存的清除是在方法运行之前执行,无论方法是否出现异常,缓存都清除;
*/
beforeInvocation = true)
public void deleteEmp(Integer id){
employeeMapper.deleteEmpById(id);
}
@Caching注解:定义缓存规则
@Caching(
cacheable = {
@Cacheable(value="emp",key = "#lastName")/*通过lastName来进行缓存查询*/
},
put = {
@CachePut(value="emp",key = "#result.id"),/*通过结果的id来进行缓存更新*/
@CachePut(value="emp",key = "#result.email" /*通过结果的email来进行缓存更新*/)
},
evict = {
@CacheEvict(value="emp",key = "#id")/*通过id来进行缓存清除*/
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
@CacheConfig注解:抽取缓存的公共配置
@CacheConfig(cacheNames="emp", /*指定cacheNames/value 为 emp */
cacheManager = "employeeCacheManager") /*指定cacheManager 为 employeeCacheManager*/
@Service
public class EmployeeService {
...
}