From b894b5bbb697fc57add00dcc31615acb0b0e104b Mon Sep 17 00:00:00 2001 From: Rikako Wu <496063163@qq.com> Date: Wed, 1 Feb 2023 11:08:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AF=B9spring=20cache?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=9A=84=E9=98=85=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring/spring cache/spring cache.md | 89 +++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/spring/spring cache/spring cache.md b/spring/spring cache/spring cache.md index 878ef6c..03a1c51 100644 --- a/spring/spring cache/spring cache.md +++ b/spring/spring cache/spring cache.md @@ -1,3 +1,22 @@ +- [Spring Cache](#spring-cache) + - [Cache Abstract](#cache-abstract) + - [使用cache abstraction的要点](#使用cache-abstraction的要点) + - [缓存可能会存在的问题](#缓存可能会存在的问题) + - [基于声明式注解的缓存](#基于声明式注解的缓存) + - [@Cacheable](#cacheable) + - [默认的key生成](#默认的key生成) + - [自定义key生成的方式](#自定义key生成的方式) + - [sync caching](#sync-caching) + - [condition cache](#condition-cache) + - [@Cacheable和Optional](#cacheable和optional) + - [@CachePut](#cacheput) + - [@CacheEvict](#cacheevict) + - [@Caching](#caching) + - [@CacheConfig](#cacheconfig) + - [@EnableCaching](#enablecaching) + - [配置cache 存储](#配置cache-存储) + - [Cache Redis](#cache-redis) + # Spring Cache ## Cache Abstract Cache针对java方法进行缓存,当想要获取的信息在cache中可获取时,可以从cache中进行获取,从而降低了java方法的执行次数。 @@ -75,3 +94,73 @@ cache abstraction支持Optional类型,如果Optional对象的value不为空, @Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result?.hardback") public Optional findBook(String name) ``` +### @CachePut +在不影响方法执行的情况下,要将方法的执行结果更新到cache中,可以使用@CachePut注解。标注了@CachePut的方法总会被执行,并且执行的返回结果会被更新到cache中。 +@CachePut注解支持和@Cacheable相同的参数,且@CachePut用于的是缓存的注入,而不应用于优化方法流程。 +@CachePut的使用如下所示: +```java +@CachePut(cacheNames="book", key="#isbn") +public Book updateBook(ISBN isbn, BookDescriptor descriptor) +``` +> @CachePut注解和@Cacheable注解通常情况下不应用于同一方法上 + +### @CacheEvict +cache abstraction不仅支持缓存的注入,而且支持缓存的淘汰,该淘汰过程可以从缓存中移除过时或未使用的数据。 +@CacheEvict注解具有allEntries属性,将该属性标记为true可以逐出所有的缓存条目: +```java +// 该场景下,cache中的条目将会被清空 +// 该场景下并不是依此逐出所有的key,而是一次性清空所有缓存 +@CacheEvict(cacheNames="books", allEntries=true) +public void loadBooks(InputStream batch) +``` +可以为@CacheEvict注解指定beforeInvocation属性,来指定该eviction行为是否应该在@CacheEvict方法被调用之前执行: +- 默认情况下,beforeInvocation属性的默认值为false,eviction操作在方法成功返回之后才执行(如果该方法被cached或执行时抛出异常,eviction操作不会执行) +- 如果beforeInvocation属性被设置为true,代表该eviction行为在方法被调用之前就会被执行 +### @Caching +如果想要指定同一类型的多个注解(例如@CacheEvict或CachePut),例如对不同的cache,condition和key expression不同。 +@Caching注解允许对同一方法内嵌多个@Cacheable、@CachePut、@CacheEvict注解,使用示例如下: +```java +@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") }) +public Book importBooks(String deposit, Date date) +``` +### @CacheConfig +在使用cache注解时,可能在同一个类中需要为所有cache operation指定相同的选项(例如为类中所有的cache注解指定相同的cache name)。此时,可以通过一个class-level的@CacheConfig注解来指定类中所有cache operation的相同选项: +```java +@CacheConfig("books") +public class BookRepositoryImpl implements BookRepository { + + @Cacheable + public Book findBook(ISBN isbn) {...} +} +``` +> 通过@CacheConfig注解指定的属性可以在cache operation中被覆盖 + +### @EnableCaching +想要在项目中启用所有的缓存注解,需要在一个@Configuration类上指定@EnableCaching注解 +## 配置cache 存储 +cache abstraction提供了一些存储集成选项。如果没有指定任何cache library,那么spring boot会自动装配一个simple provider,该provider使用concurrent map来进行缓存存储。当需要一个cache时,cache provider会创建一个cache并返回给调用者。 +### Cache Redis +如果redis在项目中配置并且可以获取,那么spring boot会自动配置一个RedisCacheManager。可以在启动时配置其他cache,通过在properties文件中指定spring.cache.cache-names属性,并且cache的默认属性可以通过spring.cache.redis.*属性来进行配置: +```properties +spring.cache.cache-names=cache1,cache2 +spring.cache.redis.time-to-live=10m +``` +> 默认情况下,对于不同的cache,会添加一个key前缀,继而如果两个不同的cache使用相同的key,不会出现key冲突的情况 + +如果想要更细粒度的对cache进行配置,可以通过如下方式进行配置: +```java +@Configuration(proxyBeanMethods = false) +public class MyRedisCacheManagerConfiguration { + + @Bean + public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() { + return (builder) -> builder + .withCacheConfiguration("cache1", RedisCacheConfiguration + .defaultCacheConfig().entryTtl(Duration.ofSeconds(10))) + .withCacheConfiguration("cache2", RedisCacheConfiguration + .defaultCacheConfig().entryTtl(Duration.ofMinutes(1))); + + } + +} +``` \ No newline at end of file