1、创建项目
Next
Next
Next
finish
spring boot 整合 mybatis省略
启动类上加上允许缓存注解
package com.laoxu.cache;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@MapperScan("com.laoxu.cache.mapper")
@SpringBootApplication
@EnableCaching
public class Springboot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01CacheApplication.class, args);
}
}
在service层的方法上加上cacheable注解对这个方法进行缓存
package com.laoxu.cache.service.impl;
import com.laoxu.cache.bean.Employee;
import com.laoxu.cache.mapper.EmployeeMapper;
import com.laoxu.cache.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
@Cacheable/@CachePut/@CacheEvict 主要的参数
cacheNames/value | 指定缓存组件的名字,将方法的返回结果放在哪个缓存中 |
key | 缓存数据使用的key,通过key获取缓存的数据,默认是方法参数的值作为key |
keyGenerator | key的生成器,可以自定义生成的key |
condition | 符合条件下才 缓存 |
unless | 符合条件下,不缓存 |
sync | 是否开启异步模式 |
SPEL元数据对照表
三个缓存操作注解默认执行时机
@Cacheable | 方法执行之前执行,查询缓存中是否包含缓存数据?取缓存 : 创缓存 |
@CachePut | 方法执行之后执行,更新缓存,缓存中有数据? 更新缓存 : 创建缓存 |
@CacheEvict | 方法执行之后执行,清除缓存 |
@Cacheable
案例一、
使用 方法名[参数值] 作为缓存的key
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp", key = "#root.methodName+'['+#id+']'")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
案例二、
自定义key生成策略,使用 方法名[参数值] 作为缓存的key
创建自定义key生成配置类
package com.laoxu.cache.config;
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... objects) {
return method.getName() + "[" + Arrays.asList(objects).toString() + "]";
}
};
}
}
在方法上使用自定义key
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp", keyGenerator = "myKeyGenerator")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
案例三、
只对id>1的数据做缓存
spel表达式:a0、p0、#root.args[0] 都表示方法的第一个参数
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp", keyGenerator = "myKeyGenerator", condition = "a0>1")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
使用spel加上 方法名为aaa 限定条件
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp", keyGenerator = "myKeyGenerator", condition = "a0>1 and #root.methodName eq 'aaa'")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
案例四、
只缓存 id>1 且 id!=2 的数据
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp", keyGenerator = "myKeyGenerator", condition = "a0>1 and #root.methodName eq 'aaa'")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
}
@CachePut
案例、
在更新数据时 更新缓存,案例为 更新emp缓存中key为参数id值的缓存数据,须配合@Cacheable使用
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
@Override
@CachePut(cacheNames = "emp", key = "#result.id")
public Employee updateEmployee(Employee employee) {
System.out.println("更新" + employee);
employeeMapper.updateEmployee(employee);
return employee;
}
}
在有缓存的情况下,调用getEmployee()方法则会去缓存取出key为参数id值的方法返回结果,若此时调用updateEmployee()方法则会将key为id值的缓存数据更新为新的数据,此时若再次调用getEmployee()方法则得到的是更新后的结果。
@CacheEvict
案例一、
清除emp缓存中key为参数id值的缓存数据
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
@Override
@CachePut(cacheNames = "emp", key = "#result.id")
public Employee updateEmployee(Employee employee) {
System.out.println("更新" + employee);
employeeMapper.updateEmployee(employee);
return employee;
}
@Override
@CacheEvict(cacheNames = "emp", key = "#id")
public void deleteEmployee(Integer id) {
System.out.println("删除" + id);
}
}
在id为1有缓存的情况下,再次获取则不查询数据库,若调用deleteEmployee(1)方法,则清除 id=1的数据缓存,那么再次调用getEmployee(1)时,会再次重新查询数据库添加缓存,而调用getEmployee(2)或其他(除了1)则无需查询数据库。
案例二、
清除emp缓存中所有缓存数据
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
@Cacheable(cacheNames = "emp")
public Employee getEmployee(Integer id) {
System.out.println("查询" + id + "号员工");
return employeeMapper.getEmployee(id);
}
@Override
@CachePut(cacheNames = "emp", key = "#result.id")
public Employee updateEmployee(Employee employee) {
System.out.println("更新" + employee);
employeeMapper.updateEmployee(employee);
return employee;
}
@Override
@CacheEvict(cacheNames = "emp", key = "#id")
public void deleteEmployee(Integer id) {
System.out.println("删除" + id);
}
@Override
@CacheEvict(cacheNames = "emp", allEntries = true)
public void deleteAllEmployee() {
System.out.println("删除所有");
}
}
调用deleteAllEmployee()则清除emp缓存中的所有缓存数据,任何缓存都需要重新添加。
案例三、
方法调用前清除emp缓存中key为参数id值的缓存数据
@Override
@CacheEvict(cacheNames = "emp", beforeInvocation = true)
public void deleteEmployeeById(Integer id) {
System.out.println("删除" + id);
}
默认CacheEvict是方法调用你后执行,若方法执行过程中抛出异常中断了,那么久清除不了缓存了,beforeInvocation缺省为false,设置为true那么执行方法过程中无论抛出异常与否,都清除缓存。