Spring Cache
Spring Cache用于对主流的缓存组件(Redis,EhCache,GuavaCache,JCache等)进行集成,提供统一的,基于注解的缓存功能(利用Spring AOP特性)。
常用注解:
-
@Cacheable
一般使用在查询方法。方法的返回值会被缓存。下一次查询,会先检查缓存中是否存在:
如果有,则直接返回,不再调用方法体;
如果没有,则调用方法,然后把结果放入缓存。
- value与cacheNames本质相同,定义缓存名称
- key:设置key。
- keyGenerator:key生成器,可自定义bean。
- cacheManager:缓存管理器
- cacheResolver:缓存解析器
- condition:条件,符合条件的走缓存。支持EL脚本
- unless:除非,当里面的条件为true,则不走缓存。支持EL脚本
- sync:是否异步
-
@CachePut
一般使用在新增方法(插入)。方法的返回值会放入缓存中。
-
@CacheEvict
一般使用在更新或删除方法。清除指定的缓存。
- allEntries:是否清除缓存中的所有元素,默认false
- beforeInvocation:是否在方法体执行前进行清除缓存的操作,默认为false。设置为true,则保证了在执行删除操作中,出错也能清除缓存
-
@Caching
从源码上看是Cacheable、CachePut、CacheEvict的组合注解
-
@CacheConfig
上述的4个注解都作用于方法上,
@CacheConfig
作用于类上,用于统一设定。
上手使用
-
maven中添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
配置文件中添加Redis相关配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8 username: root password: Root@1234 type: com.alibaba.druid.pool.DruidDataSource redis: host: 127.0.0.1 port: 6379 database: 1 password: redis.123456 jedis: pool: max-active: 20 max-idle: 20 min-idle: 5 max-wait: 1000ms
-
启动类添加注解
@EnableCaching
开启Spring Cache -
编写demo,并使用注解。
-
@Cacheable
代码:
@Override @Cacheable(cacheNames = "user",key = "#id",condition = "#id < 10") public User findUserById(Integer id) { log.info("执行UserServiceImpl#findUserById(Integer)。。。"); return userDAO.findUserById(id); }
工具模拟访问
查看控制台日志
可以看到,UserServiceImpl#findUserById(Integer)只执行了一次,后续的访问,都去缓存中取数据。那么这里登陆Redis客户端工具进行查看:
注:默认的key的规则为:
cacheNames
+::
+key
(value
+::
+key
)这里查询userID大于10的情况:
redis中也没有该缓存。
-
@CachePut
@Override @CachePut(cacheNames = "user",key = "#user.id") public User createUser(User user) { log.info("执行UserServiceImpl#createUser(User)。。。"); userDAO.createUser(user); return user; }
-
@CacheEvict
@Override @CacheEvict(value = "user",key = "#id") public int deleteUser(Integer id) { log.info("执行UserServiceImpl#deleteUser(Integer)。。。"); return userDAO.deleteUser(id); }
这里图的验证就不上了,可以自行验证了。
-
-
补充
从Redis客户端工具中,我们看到value的值默认使用的是JDK的序列化方式(实体类User实现了
Serializable
接口)。方便查看,我们可以改为Json序列化的方式:@Bean public RedisCacheConfiguration redisCacheConfiguration(){ return RedisCacheConfiguration.defaultCacheConfig(). serializeValuesWith(RedisSerializationContext. SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); }
这里还需添加依赖:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency>
Redis还支持其他的序列化方式:
-
扩展
详细使用,参见官网文档:Spring Boot Doc