SpringBoot的EnableCaching简述

打印 上一主题 下一主题

主题 977|帖子 977|积分 2931

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Spring Boot中的EnableCaching简述

spring boot中自带有数据缓存机制,主要通过其org.springframework.cache包下的各种类来实现。
EnableCaching

@EnableCaching是启用缓存的注解,标注在任何一个可自动注入的类上即可开启。
Cacheable

@Cacheable是一个标注与类与方法上的注解,用于表示此类或此方法需要使用缓存机制。当类与方法上都有时,采用 就近原则
在@Cacheable注解中,有一些常用参数可以进行配置:

  • value与cacheNames - 表示绑定的缓存名称。这里的缓存指的是单个的缓存存储器,并不是最终的键值对缓存对象。
  • key - 表示缓存对象的 key,这个才是最终的缓存键值对的 key。这里的参数需要使用 SpEL表达式。
  • keyGenerator - 表示用于生成此方法 缓存key的类。与key参数只能选择一个添加,否则会抛出IllegalStateException异常。
  • cacheManager - 指定缓存管理器。这个后面再细说。
  • condition - 缓存的条件。支持SpEL,当缓存条件满足时,才会进入缓存取值模式。
  • unless - 排除的条件。支持SpEL,当排除的条件满足时,会直接调用方法取值。
  • sync - 异步缓存模式。是否采用异步的方式,在方法取值时异步缓存。默认false,在缓存完成后才返回值。
一般情况下,可以这样使用:
  1. @RestController
  2. @RequestMapping("cache")
  3. @Cacheable(value = "cache", sync = true)
  4. public class CacheController {
  5.     @Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator")
  6.     @GetMapping("hello")
  7.     public String hello(String name) {
  8.         System.out.println("name - " + name);
  9.         return "hello " + name;
  10.     }
  11.     @GetMapping("hello2")
  12.     public String hello2(@RequestParam(defaultValue = "1") Integer size, @RequestParam(defaultValue = "world") String name) {
  13.         System.out.println("name - " + name);
  14.         return "hello " + name;
  15.     }
  16. }
复制代码

  • 这里的CacheController被标记上了@Cacheable(value = "cache", sync = true),表示其下的方法默认使用名为cache的缓存存取器,并采用异步的方式进行缓存处理。
  • hello方法上同样添加了@Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator"),使得hello方法使用了独立的缓存设置,并通过myKeyGenerator的策略来生成 缓存key
CachePut

将方法返回值存入到缓存中,一般情况下是用在更新操作中,并于Cacheable与CacheEvict配合使用。
CacheEvict

清除缓存值,一般用在删除或更新操作中,并于Cacheable与CachePut配合使用。
并且在CacheEvict注解中,多了两个参数:

  • allEntries - 清除当前value下的所有缓存。
  • beforeInvocation - 在方法执行前清除缓存。
示例代码示例如下:
  1.     @Cacheable(value = "c", key = "123")
  2.     @GetMapping("hello")
  3.     public String hello(String name) {
  4.         System.out.println("name - " + name);
  5.         return "hello " + name;
  6.     }
  7.     @GetMapping("/put")
  8.     @CachePut(value = "c", key = "123")
  9.     public String put() {
  10.         return "hello put";
  11.     }
  12.     @GetMapping("/evict")
  13.     @CacheEvict(value = "c", key = "123")
  14.     public String evict() {
  15.         return "hello put";
  16.     }
复制代码
上述代码中,访问hello接口时,会从c缓存存取器中取出key为123的缓存数值,没有则会调用方法并进行缓存。
访问put接口时,会将c缓存存取器key为123的缓存值改为hello put,没有则进行缓存。
访问evict接口时,会将c缓存存取器key为123的缓存值删除,此时访问hello接口会重新调用方法并进行缓存。
CacheConfig

@CacheConfig作为类上的注解,目的是为了统一配置其下的方法缓存参数,并设定共享缓存名。

  • cacheNames - 共享缓存名数组。设定后表示此类下的方法缓存会依次从这些缓存存取器中取值,如果有,则取用缓存值;若没有则调用方法取值,并缓存值到设定的所有缓存存取器中。
CacheManager

缓存管理器接口,用来做缓存管理的类。一般我们需要自定义缓存策略时,就是从CacheManager来入手的。
直接上实例:
  1. @Component
  2. public class MyCacheManager implements CacheManager, InitializingBean {
  3.     private final Map<String, Cache> cacheMap;
  4.     public MyCacheManager() {
  5.         cacheMap = new HashMap<>();
  6.     }
  7.     @Override
  8.     public Cache getCache(String name) {
  9.         System.out.println("正在获取缓存 - " + name);
  10.         return cacheMap.computeIfAbsent(name, MyCache::new);
  11.     }
  12.     @Override
  13.     public Collection<String> getCacheNames() {
  14.         return cacheMap.keySet();
  15.     }
  16.     @Override
  17.     public void afterPropertiesSet() throws Exception {
  18.         System.out.println("say something!");
  19.     }
  20. }
复制代码
CacheManager有两个方法需要被实现:

  • getCache(String) - 获取缓存存取器。这里的name其实就对应了@Cacheable注解中的value与cacheName参数。
  • getCacheNames - 获取类中所有缓存的名称集合。这主要是为了Spring内部的统一管理需要。
    因为 Spring采用了默认替补策略,所以我们使用@Component或是通过@Bean自动注入后,默认的缓存管理器就会切换成我们自定义的。如果我们自定义了两个的话,可以通过@Primary来设定默认管理器。
Cache

缓存存取器,用来管理缓存键值对的基本单元。
为了能对不同的缓存采用不同的存取策略,我们可以定制不同的Cache,并通过自定义的CacheManager的getCache方法返回对应的Cache。
举个例子:
  1. public final static class MyCache extends ConcurrentMapCache {
  2.     public MyCache(String name) {
  3.         super(name);
  4.     }
  5.     @Override
  6.     public <T> T get(Object key, Class<T> type) {
  7.         System.out.println("正在读取 - " + key);
  8.         return super.get(key, type);
  9.     }
  10.     @Override
  11.     public <T> T get(Object key, Callable<T> valueLoader) {
  12.         System.out.println("正在读取 - " + key);
  13.         return super.get(key, valueLoader);
  14.     }
  15.     @Override
  16.     public ValueWrapper get(Object key) {
  17.         System.out.println("正在读取 - " + key);
  18.         return super.get(key);
  19.     }
  20. }
复制代码
这里的MyCache集成了ConcurrentMapCache,并对每次缓存值的获取都进行了控制台输出。
KeyGenerator

缓存key生成器,用于自定义规则缓存key的生成。
其接口的方法只有一个:
  1. public interface KeyGenerator {
  2.     Object generate(Object target, Method method, Object... params);
  3. }
复制代码
一目了然,通过调用的目标对象、目标方法与方法入参进行key的生成。这里不做过多赘述。
不过需要注意的是,由于不同类可能有同名同参数的方法,这里建议加上target.getClass().getName()来作为标记,避免出现不希望的缓存映射。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

何小豆儿在此

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表