springboot缓存注解:
1.JSR107:
Java Cache定义了5个核心接口:CachingProvider,CacheManager,Cache,Entry和Expiry
CachingProvider创建配置获取控制多个CacheManager,
CacheManager创建配置获取控制唯一命名的Cache,
Cache是一个类似Map的数据结构并临时存储以Key为索引的值,
Entry是Key-Value对,Expiry是有效期。
需要导入javax.cache包
<dependency>
<groupId>javax.cache</groupId>
<atrifactId>cache-api</atrifactId>
</dependency>
2.spring缓存抽象
Cache | 缓存接口,定义缓存操作,实现有:RedisCache,EhCacheCahe,ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(Cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
3.使用Cache
@SpringBootApplication
@MapperScan("com.bootbootboot.springboot01cache.mapper")
@EnableCaching //开启基于注解的缓存
public class Springboot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01CacheApplication.class, args);
}
}
package com.bootbootboot.springboot01cache.service;
import com.bootbootboot.springboot01cache.bean.Employee;
import com.bootbootboot.springboot01cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
//@CacheConfig(cacheNames = "emp") //抽取缓存的公共配置,不用在每个注解上标识
@Service
public class EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
/**
* 默认使用ConcurrentMapCacheManager == ConcurrentMapCache:将数据保存在ConcurrentMap<Obejct>
* 开发中使用缓存中间件:redis,memcached,ehcache;
*/
/**
* 将方法的运行结果进行缓存,以后直接从缓存中获取,不用调用方法
* CacheManager缓存管理器:管理多个Cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字。
* 几个属性:
* cacheName/value:指定缓存组件的名字;将方法的返回值结果放在哪个缓存中,是数组的方式,可以指定多个缓存
* key:缓存数据使用的key(可使用SpEL编写#id:参数id的值 #a0 #p0 #root.args[0]):可以用它来指定,默认使用方法参数。值为返回的信息。
* keyGenerator:key的生成器,可以自己指定key的生成器的组件id
* key/keyGenerator:二选一使用
* 注:keyGenerator 需要自己配置
*
* cacheManager/cacheResolver:指定缓存管理器
* condition:指定符合条件的情况下才缓存 eg:#a0>1 第一个参数大于一的时候才缓存
* unless:否定缓存,方法的返回值不会缓存,可以获取结果进行判断
* sync:是否使用异步模式
* 原理:
* 1.自动配置类:CacheAutoConfiguration
* 2.缓存配置类:运行是加载
* 3.那些配置类默认生效:SimpleCacheConfiguration【默认】
* 4.给容器中注册了一个CacheManager:ConcurrentMapCacheManager
* 5.可以获取和创建ConcurrentMapCache类型的缓存组件:他的作用是将数据保存在ConcurrentMap中。
* 运行流程:
* 1.方法运行前,先去查询Cache(缓存组件),按照cacheName指定的名字
* (cacheManager先获取相应的缓存),第一次获缓存如果没有会自动创建
* 2.去cache查找缓存的内容,使用一个key,默认就是方法的参数。key就是按照某种策略生成(【默认】使用keyGenerator生成)。
* SimpleKeyGenerator的key生成策略:
* 如果没有参数,key:new SimpleKey();
* 如果有一个参数:key = 参数值
* 如果有多个参数:key = new SimpleKey(params);
* 3.没有查到缓存就调用目标方法
* 4.将目标方法返回的结果,放进缓存中
*
* @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法,并将结果放入缓存,以后再来调用就可以直接使用缓存中的数据
*
* 核心:
* 1.使用CacheManager按照名字得到Cache(ConcurrentMapCache)组件
* 2.key使用keyGenerator生成的,默认是SimpleKeyGenerator
*/
@Cacheable(cacheNames = {"emp"},key = "#id>0") //等于 key=“#root.args[0]”
public Employee getEmployee(Integer id) {
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
//配置
@Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator",condition = "#a0>1") //第一个参数大于一的时候才缓存
public Employee getEmployee2(Integer id) {
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
/**
* @CachePut:即调用方法,又更新缓存数据
* 修改了数据库的某个数据,同时更新缓存
* 运行时机:
* 1.先调用目标方法
* 2.将目标方法的结果缓存起来
* 注意:更新的缓存key一定要设置好,应该是更新后的员工:
* key = “#employee.id” : 使用传入的参数的员工id
* key = "#result.id" : 使用返回后的id
* @Cacheable的key是不能用#result
*/
@CachePut(value = "emp",key = "#result.id")
public Employee updateEmp(Employee employee){
employeeMapper.updateEmp(employee);
return employee;
}
/**
* @CacheEvict :清除缓存
* key: 指定要清除的数据
* allEntries = true:全部清空
* beforeInvocation = false :缓存的清除是否在方法之前执行,无论是否出现异常,缓存都清除
*/
@CacheEvict(value = "emp",key = "#id")
public void deleteEmp(Integer id){
employeeMapper.deleteEmpById(id);
}
/**
* @Caching: 复杂的缓存规则
*/
@Caching(
cacheable = {
@Cacheable(value = "emp",key = "lastName")
},
put = {
@CachePut(value = "emp",key = "#result.id"),
@CachePut(value = "emp",key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
}
扩展:使用配置类使用缓存
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.util.Arrays;
@Configuration
public class MyCacheConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator(){
@Override
public Object generate(Object o, Method method, Object... params) {
return method.getName()+"["+ Arrays.asList(params).toString()+"]";
}
};
}
}