spring boot中自带有数据缓存机制,主要通过其org.springframework.cache
包下的各种类来实现。
(资料图片)
@EnableCaching
是启用缓存的注解,标注在任何一个可自动注入的类上即可开启。
@Cacheable
是一个标注与类与方法上的注解,用于表示此类或此方法需要使用缓存机制。当类与方法上都有时,采用 就近原则。
在@Cacheable
注解中,有一些常用参数可以进行配置:
value
与cacheNames
- 表示绑定的缓存名称。这里的缓存指的是单个的缓存存储器,并不是最终的键值对缓存对象。key
- 表示缓存对象的 key,这个才是最终的缓存键值对的 key。这里的参数需要使用 SpEL表达式。keyGenerator
- 表示用于生成此方法 缓存key的类。与key
参数只能选择一个添加,否则会抛出IllegalStateException
异常。cacheManager
- 指定缓存管理器。这个后面再细说。condition
- 缓存的条件。支持SpEL,当缓存条件满足时,才会进入缓存取值模式。unless
- 排除的条件。支持SpEL,当排除的条件满足时,会直接调用方法取值。sync
- 异步缓存模式。是否采用异步的方式,在方法取值时异步缓存。默认false
,在缓存完成后才返回值。一般情况下,可以这样使用:
@RestController@RequestMapping("cache")@Cacheable(value = "cache", sync = true)public class CacheController { @Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator") @GetMapping("hello") public String hello(String name) { System.out.println("name - " + name); return "hello " + name; } @GetMapping("hello2") public String hello2(@RequestParam(defaultValue = "1") Integer size, @RequestParam(defaultValue = "world") String name) { System.out.println("name - " + name); return "hello " + name; }}
这里的CacheController
被标记上了@Cacheable(value = "cache", sync = true)
,表示其下的方法默认使用名为cache
的缓存存取器,并采用异步的方式进行缓存处理。hello
方法上同样添加了@Cacheable(value = "hello", sync = true, keyGenerator = "myKeyGenerator")
,使得hello
方法使用了独立的缓存设置,并通过myKeyGenerator
的策略来生成 缓存key。CachePut将方法返回值存入到缓存中,一般情况下是用在更新操作中,并于Cacheable
与CacheEvict
配合使用。
清除缓存值,一般用在删除或更新操作中,并于Cacheable
与CachePut
配合使用。
并且在CacheEvict注解中,多了两个参数:
allEntries
- 清除当前value
下的所有缓存。beforeInvocation
- 在方法执行前清除缓存。示例代码示例如下:
@Cacheable(value = "c", key = "123") @GetMapping("hello") public String hello(String name) { System.out.println("name - " + name); return "hello " + name; } @GetMapping("/put") @CachePut(value = "c", key = "123") public String put() { return "hello put"; } @GetMapping("/evict") @CacheEvict(value = "c", key = "123") public String evict() { return "hello put"; }
上述代码中,访问hello
接口时,会从c缓存存取器中取出key为123
的缓存数值,没有则会调用方法并进行缓存。
访问put
接口时,会将c缓存存取器中key为123
的缓存值改为hello put
,没有则进行缓存。
访问evict
接口时,会将c缓存存取器中key为123
的缓存值删除,此时访问hello
接口会重新调用方法并进行缓存。
@CacheConfig
作为类上的注解,目的是为了统一配置其下的方法缓存参数,并设定共享缓存名。
cacheNames
- 共享缓存名数组。设定后表示此类下的方法缓存会依次从这些缓存存取器中取值,如果有,则取用缓存值;若没有则调用方法取值,并缓存值到设定的所有缓存存取器中。CacheManager缓存管理器接口,用来做缓存管理的类。一般我们需要自定义缓存策略时,就是从CacheManager
来入手的。
直接上实例:
@Componentpublic class MyCacheManager implements CacheManager, InitializingBean { private final Map cacheMap; public MyCacheManager() { cacheMap = new HashMap<>(); } @Override public Cache getCache(String name) { System.out.println("正在获取缓存 - " + name); return cacheMap.computeIfAbsent(name, MyCache::new); } @Override public Collection getCacheNames() { return cacheMap.keySet(); } @Override public void afterPropertiesSet() throws Exception { System.out.println("say something!"); }}
CacheManager
有两个方法需要被实现:
getCache(String)
- 获取缓存存取器。这里的name
其实就对应了@Cacheable
注解中的value
与cacheName
参数。getCacheNames
- 获取类中所有缓存的名称集合。这主要是为了Spring
内部的统一管理需要。因为 Spring采用了默认替补策略,所以我们使用@Component
或是通过@Bean
自动注入后,默认的缓存管理器就会切换成我们自定义的。如果我们自定义了两个的话,可以通过@Primary
来设定默认管理器。Cache缓存存取器,用来管理缓存键值对的基本单元。为了能对不同的缓存采用不同的存取策略,我们可以定制不同的Cache
,并通过自定义的CacheManager
的getCache
方法返回对应的Cache
。举个例子:
public final static class MyCache extends ConcurrentMapCache { public MyCache(String name) { super(name); } @Override public T get(Object key, Class type) { System.out.println("正在读取 - " + key); return super.get(key, type); } @Override public T get(Object key, Callable valueLoader) { System.out.println("正在读取 - " + key); return super.get(key, valueLoader); } @Override public ValueWrapper get(Object key) { System.out.println("正在读取 - " + key); return super.get(key); }}
这里的MyCache
集成了ConcurrentMapCache
,并对每次缓存值的获取都进行了控制台输出。
缓存key生成器,用于自定义规则缓存key的生成。其接口的方法只有一个:
public interface KeyGenerator { Object generate(Object target, Method method, Object... params);}
一目了然,通过调用的目标对象、目标方法与方法入参进行key的生成。这里不做过多赘述。不过需要注意的是,由于不同类可能有同名同参数的方法,这里建议加上target.getClass().getName()
来作为标记,避免出现不希望的缓存映射。
什么情形应当认定工伤?时间上有要求吗?请收好这份工伤认定知识帖!
【一鸣专栏】内耗的家庭是给孩子最可怕的礼物原创作者|一鸣很多人都说,家是温暖的港湾,当你出门在外漂泊疲乏之时,家总能带给你能量,让你恢
近期,美国硅谷银行和签名银行相继关闭,引发美国和欧洲银行业动荡。本月19日,瑞士联邦政府宣布瑞士信贷银行将被瑞银集团收购。美国市场观察
今天青岛海尔股票行情观念:成绩平稳,且短期走势加强,可继续持有或买入6月30日:短线大盘还有回调要求7月行情今天可申购
1、游戏王者荣耀:本期视频带给大家的是王者荣耀模拟战强势3套阵容!菜小鸟一直在努力。2、认真不放弃。3、你们的陪伴是我最大的动力!订阅关