一、测试缓存
1、默认情况
默认情况,SpringBoot 会使用 SimpleCacheConfiguration 缓存配置类。
然后创建一个 ConcurrentMapCacheManager 缓存管理器,可以获取 ConcurrentMap 来作为缓存组件使用。
2、使用 Redis
(1)引入 redis 的 starter 后,RedisCacheConfiguration 缓存配置类就会生效,会创建一个 RedisCacheManager。
(2)RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件,RedisCache 通过操作 Redis 来存取数据;
(3)测试
@Cacheable(cacheNames = {"emp"})
public Employee getEmpById(Integer id) {
System.out.println("查询" + id +"号员工");
return employeeMapper.getEmpById(id);
}
会以 Redis 做为缓存来存取数据。
默认保存数据 k-v 都是 Object,利用序列化保存的,如何保存为 JSON呢?
(4)RedisCacheManager
引入 redis 的 starter之后,cacheManager 变为 RedisCacheManager。
默认创建的 RedisCacheManager 在操作 redis 的时候 RedisTemplate<Object, Object>。
RedisTemplate<Object, Object> 是默认使用JDK的序列化机制。
(5)如果我们想要保存为 JSON 格式就可以自定义 CacheManager。
二、自定义 CacheManager
1、自定义操作 Employee 的 CacheManager
(1)自定义 RedisTemplate
@Bean
public RedisTemplate<Object, Employee> empRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Employee> template = new RedisTemplate<Object, Employee>();
//设置默认的序列化器
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Employee>(Employee.class));
template.setConnectionFactory(redisConnectionFactory);
return template;
}
(2)自定义 CacheManager
//CacheManagerCustomizers 可以来定制缓存的一些规则
@Bean
public RedisCacheManager empCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
(3)测试
@Cacheable(cacheNames = {"emp"})
public Employee getEmpById(Integer id) {
System.out.println("查询" + id +"号员工");
return employeeMapper.getEmpById(id);
}
现在就可以保存为 JSON 格式的 Employee 数据了。
但是,还有一个问题?如果存取的是其他的 JavaBean 呢?
/**
* 缓存的数据能存入 redis
* 第二次从缓存中查询就不能反序列化回来
* 存的是 dept 的 json 数据, CacheManager 默认使用RedisTemplate<Object, Employee> empRedisTemplate 来操作 Redis 的
*
*
* @param id
* @return
*/
@Cacheable(cacheNames = "dept")
public Department getDeptById(Integer id){
System.out.println("getDeptById查询部门:" + id);
return departmentMapper.getDeptById(id);
}
出错了!!!
原因:存的是 dept 的 json 数据, CacheManager 默认使用RedisTemplate<Object, Employee> empRedisTemplate 来操作 Redis 的
2、自定义操作 Department 的 CacheManager
(1)自定义 RedisTemplate
@Bean
public RedisTemplate<Object, Department> deptRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate<Object, Department>();
//设置默认的序列化器
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Department>(Department.class));
template.setConnectionFactory(redisConnectionFactory);
return template;
}
(2)自定义 CacheManager
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
(3)测试
但是现在容器中有两个 CacheManager(EmpCacheManager 和 DeptCacheManager),所以操作缓存的时候还需要指定 CacheManager。
可以使用 @CacheConfig 在类上进行统一的配置。
@CacheConfig(cacheNames = {"dept"}, cacheManager = "deptCacheManager")
@Service
public class DepartmentService {
@Autowired
DepartmentMapper departmentMapper;
@Cacheable(cacheNames = "dept")
public Department getDeptById(Integer id){
System.out.println("getDeptById查询部门:" + id);
return departmentMapper.getDeptById(id);
}
}
也可以在 @Cacheable 注解上面指定:
1 | @Cacheable (cacheNames = "dept" , cacheManager = "deptCacheManager" ) |
此时就可以同时使用 EmpCacheManager 与 DeptCacheManager了。
(4)以编码方式使用缓存
@Qualifier("deptCacheManager")
@Autowired
RedisCacheManager deptCacheManager;
//直接使用缓存管理器得到缓存,进行调用即可
public Department getDept(Integer id){
System.out.println("getDeptById查询部门:" + id);
Department dept = departmentMapper.getDeptById(id);
//获取某个缓存
Cache cache = deptCacheManager.getCache("dept");
cache.put("dept:1", dept);
return dept;
}
3、指定首选的 CacheManager
当在容器中配置了多个 CacheManager,如果没有指定使用哪个 CacheManager,就会报错,所以需要指定一个默认的首选配置,我们可以把 RedisCacheConfiguration 中的RedisCacheManager 作为首选的CacheManager。
代码示例:
//CacheManagerCustomizers 可以来定制缓存的一些规则
@Bean
public RedisCacheManager empCacheManager(RedisTemplate<Object, Employee> empRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Bean
public RedisCacheManager deptCacheManager(RedisTemplate<Object, Department> deptRedisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(deptRedisTemplate);
//使用前缀,将 CacheName 作为key 的前缀
cacheManager.setUsePrefix(true);
return cacheManager;
}
@Primary //将某个缓存管理器作为默认使用的
@Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
return cacheManager;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?