缓存介绍
Spring3.1之后引入了基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(如EHCache 或者Redis),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种annotation,即能够达到缓存方法的返回对象的效果。
Spring的缓存技术还具备相当的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的key和各种condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存,例如Redis、EHCache集成。
Spring Cache位于spring-content中,如下图
Spring Cache涉及主要类
Spring定义了Cache和CacheManager两个基础接口类。
Cache
Cache
接口提供了其他缓存技术实现的规范,包括缓存的各种操作,增加、删除、获取缓存等。Cache默认实现缓存如下,其中Ehcache
、RedisCache
都为流行的Cache实现方法。
CacheManager
CacheManager
是Spring提供的各种缓存技术抽象接口,通过它管理Spring框架内部默认实现的CacheManager,Spring框架内部默认实现的CacheManager如下
CacheResolver
CacheResolver
解析器,用于根据实际情况来动态解析使用哪个Cache。
KeyGenerator
KeyGenerator
当使用注解时,默认key的生成规则。
Spring Cache主要的注解
@Cacheable
用于读取缓存的方法上,先从缓存中读取数据,如果没有再调用具体方法获取数据,然后将数据添加到缓存中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Cacheable {
@AliasFor("cacheNames") String[] value() default {};
@AliasFor("value") String[] cacheNames() default {};
String key() default "";
String keyGenerator() default "";
String cacheManager() default "";
String cacheResolver() default "";
String condition() default "";
String unless() default "";
boolean sync() default false; }
|
例子:
1 2 3 4 5
| @Cacheable(value = "user", key = "#id",condition = "#id.length()>0",unless = "#id==null") public User findById(String id) { return userDao.findById(id).orElseGet(User::new); }
|
@CachePut
用于保存或者更新方法上,调用方法时将相应数据存入缓存中。
例子:
1 2 3 4 5
| @CachePut(value = "user", key = "#user.id") @Transactional public User update(User user) { return userDao.save(user); }
|
@CacheEvict
用于删除方法上,删除对应缓存。
1 2 3 4 5 6 7 8 9 10
| @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface CacheEvict { ...
boolean allEntries() default false;
boolean beforeInvocation() default false;
|
例子:
1 2 3 4
| @CacheEvict(value = "user") public void delete() { ... }
|
@Caching
组合使用Cache注解
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Caching {
Cacheable[] cacheable() default {};
CachePut[] put() default {};
CacheEvict[] evict() default {};
}
|
@CacheConfig
全局Cache配置,自定义cache时需在方法上指定此注解。
@EnableCaching
开启Spring Cache的默认配置,启动缓存需要在项目中添加此注解。
Spring Boot集成
redis
支持分布式缓存,默认使用Luttuce客户端,也可采用Jedis。
引入依赖
pom.xml
1 2 3 4 5 6 7 8 9 10
| <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>
|
配置文件
application.yml
单机模式配置
1 2 3 4 5 6 7 8 9 10 11 12
| spring: application: name: coding-cache-redis
redis: host: localhost port: 6379 password: 1111 database: 0
cache: type: redis
|
哨兵模式配置
1 2 3 4 5 6 7 8 9 10 11 12
| spring: application: name: coding-cache-redis redis: sentinel: master: mymaster nodes: 192.168.81.10:26375,192.168.81.11:26376,192.168.81.12:26377 database: 3 password: 1111 cache: type: redis
|
集群模式配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| spring: application: name: coding-cache-redis redis: database: 3 password: 1111 cluster: nodes: 192.168.81.10:26375,192.168.81.11:26376,192.168.81.12:26377 max-redirects: 2 cache: type: redis
|
启动缓存
在Application启动类中使用@EnableCaching
注解启用缓存
1 2 3 4 5 6 7 8 9
| @EnableCaching @SpringBootApplication public class CodingCacheRedisApplication {
public static void main(String[] args) { SpringApplication.run(CodingCacheRedisApplication.class, args); }
}
|
具体操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Service @CacheConfig(cacheNames = "user") public class UserService { @Autowired private UserDao userDao;
@Cacheable @Transactional public User save(User user) { return userDao.save(user); }
@CachePut(key = "#user.id") @Transactional public User update(User user) { return userDao.save(user); }
@Cacheable(key = "#id", condition = "#id.length()>0", unless = "#id==null") public User findById(String id) { return userDao.findById(id).orElseGet(User::new); }
@CacheEvict @Transactional public void delete(String id) { userDao.deleteById(id); } }
|
Ehcache
EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider 。
引入依赖
1 2 3 4 5 6 7 8
| <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
|
配置文件
application.yml
1 2 3 4 5 6 7 8 9 10 11 12
| spring: application: name: coding-cache-redis
redis: host: localhost port: 6379 password: 1111 database: 0
cache: type: ehcache
|
在resources下添加ehcache.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <diskStore path="java.io.tmpdir"/> <defaultCache eternal="false" maxEntriesLocalHeap="2000" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" /> <cache name="user" maxElementsInMemory="1000" timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU"/> </cache>
</ehcache>
|
启动缓存
在Application启动类中使用@EnableCaching
注解启用缓存
1 2 3 4 5 6 7 8 9
| @EnableCaching @SpringBootApplication public class CodingCacheRedisApplication {
public static void main(String[] args) { SpringApplication.run(CodingCacheRedisApplication.class, args); }
}
|
具体操作
同redis