前言
- 假设以SpringBoot开发
当我们的数据量非常大时,不能每次都去数据库里面查找,就得使用缓存来分担数据库的压力。我们可以使用Redis作为我们的缓存数据库,但是如果把数据写入缓存的逻辑写入我们的业务代码,有两个不妥:1、代码可读性不强,简单的说就是难看。2、手累,敲那么多代码,你手不累吗?(开玩笑的,也就说要写太多的逻辑)
Spring为了简化开发人员编写缓存的逻辑,开发了spring-data-cache。emm…怎么说呢,这就是一种规范吧。如果你没有声明用哪种作为缓存的话,那么Spring就会使用你当前服务器的内存作为缓存,使用的是ConcurrentHashMap数据结构(官方文档就是这么说的)
If you do not add any specific cache library, Spring Boot auto-configures a simple provider that uses concurrent maps in memory.
如果我们在appclication.properties声明spring.cache.type=redis ,还加入了Redis的相关依赖,那么SpringBoot就会自动帮你生成一个RedisCacheManager的Bean(没有用SpringBoot则自己配置RedisCacheManager)CacheManager
CacheManager就相当于一个缓存管理器(接口),不同类型的缓存就会有不同的管理器,比如Redis的缓存管理就是RedisCacheManager ,RedisCacheManager可以设置RedisTemplate,设置存进Redis缓存的超时时间,设置生成缓存的键key..
如何使用Spring-data-cache
SpringBoot中叫spring-boot-starter-cache,引入该包开启缓存服务。如果你用Redis作为缓存的话,先配置Redis
然后配置spring.cache.* ,简单的就如下配置
然后在一个配置类上加上注解EnableCaching 开启缓存服务(大概是开启代理模式),这样的话,在Spring内部处理Bean时,会触发postProcessor(如果你懂Bean的生命周期的话)
其中一定要配置过期时间吧,不然Redis内存肯定不够用,而且数据的一致性又很难保证
如果你使用SpringBoot的话,就会自动帮你配置Redis连接池、RedisTemplate、RedisCacheManager了,你就可以直接使用了。如果你要自己配置,就声明一配置类,加上@EnableCaching,声明一个RedisTemplate的Bean,声明一个RedisCacheManager的Bean
接下来就使用注解了:@Cacheable、@CachePut、@CacheEvict
@Cacheable
先看怎么使用:
我们声明一个Service类,该类只有一个查询方法,返回一个列表,我们把列表的内存缓存进Redis1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18package com.cobuy.db.service.impl;
/**
* @author SouthLight-Lin on 2019/3/30
*/
@Service
public class DBUserServiceImpl implements DBUserService {
// 查询数据库的Mapper类(Mybatis)
@Autowired
private CobuyTypeMapper cobuyTypeMapper;
@Cacheable(value = "cobuy::cobuyTypes")
@Override
public List<CobuyType> selectCobuyTypes() {
return cobuyTypeMapper.selectAll();
}
}
作用:在进入方法前,会先去缓存里面寻找该数据是否有,有则直接返回缓存中的数据,并且不会执行你方法中的代码.如果缓存不存在,则执行查找数据的代码,并把返回的数据存进缓存。
该注解里面有value、key、condition、unless属性,各属性的作用如下:
我是这么理解的,value可以自己指定KEY,比如我的value是cobuy::cobuyTypes,那么存进Redis中键的前缀就是这个,后面还会有key,所以形式是这样的cobuy::cobuyTypes::key,如图:
如果指定key值,又因为该值只满足SPEL表达式,里面的值如下:
@CachePut
用法跟@Cacheable差不多,不同的是:先执行方法,再缓存数据。其实很好理解,我们Http的PUT请求相当于修改的请求,一个修改操作就会去修改缓存中的数据,再存储数据
注解里面的四个属性跟@Cacheable一样,见上图
@CacheEvict
作用:移除缓存对应的key值
底层原理
spring-data-cache跟Spring事务原理差不多,用到了AOP动态代理的知识,所以需要在@EnableCaching里面开启代理,注意:该注解里面有一个属性可以开启Cglib代理的配置,因为我们的缓存类不可能都是基于接口的
也就是说,最后执行的Service,不是我们编写的Service,而是经过Spring增强的代理类
类的增强发生在Bean的生命周期后置处理器的后置方法中
增强后的类为: