性能缓慢是开发人员经常面临的一个反复出现的复杂问题,解决此类问题的最常见方法之一就是利用缓存,不过,处理缓存并不是一个容易的事情。
幸运的是,自 3.1 版本开始,Spring 引入了对 Cache 的支持。其使用方法和原理都类似于 Spring 对事务管理的支持。
接下来我们了解一下如何基于注解的方式来使用 Spring 的 Cache。
启用缓存 @EnableCaching
在使用缓存注解之前,我们必须使用 @EnableCaching 来启用缓存注解。
@EnableCaching 的使用示例如下:
@SpringBootApplication
@EnableCaching
public class UserApp {
public static void main(String[] args) {
SpringApplication.run(UserApp.class);
}
}
注解 @Cacheable
将结果存储到缓存中的方法。使用此注解后,在后续调用该方法(相同的参数)时,直接去缓存中取,无需实际执行该方法。
@Cacheable 的单个缓存使用示例如下:
@Cacheable("books")
public Book findBook(ISBN isbn) {...}
在上面的代码中,findBook 方法与名为 books 的缓存相关联。每次调用该方法时,都会检查缓存,看是否已经运行过该调用,而不必重复。虽然在大多数情况下,只有一个缓存被声明,但注解允许指定多个名字,这样就可以使用多个缓存了。使用多个缓存时,每个缓存在调用方法之前都会被检查 ---- 如果至少有一个缓存被命中,相关的值会被返回。
所有其他不包含该值的缓存也会被更新,即使该缓存方法没有被实际调用。
@Cacheable 的多个缓存使用示例如下:
// 使用多个缓存示例
@Cacheable({"books", "isbns"})
public Book findBook(ISBN isbn) {...}
| 序列 | 参数 | 解释 |
|---|---|---|
| 1 | cacheNames | 指定缓存组件的名字 |
| 2 | key | 缓存数据时使用的key,默认使用方法参数 |
| 3 | keyGenerator | key 的生成器。 key 和 keyGenerator 二选一使用 |
| 4 | cacheManager | 可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。 |
| 5 | condition | 可以用来指定符合条件的情况下才缓存 |
| 6 | unless | 否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断 |
| 7 | sync | 是否使用异步模式。 |
注解 @CachePut
当需要更新缓存而不干扰方法的执行时,可以使用 @CachePut 注解。 也就是说 @CachePut 注解标注的方法总是会执行,而且会尝试将结果放入缓存(当然,是否真的会缓存还跟一些注解参数有关,比如:unless 参数)。@CachePut 更适合用于缓存的填充而不是方法流的优化。
@CachePut拥有和@Cacheable相同的选项。@Cacheable的逻辑是:查找缓存 - 有就返回 -没有就执行方法体 - 将结果缓存起来;@CachePut的逻辑是:执行方法体 - 将结果缓存起来;- 所以
@Cacheable适用于查询数据的方法,@CachePut适用于更新数据的方法。
@CachePut 的使用示例如下:
@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(Book book) {...}
在同一个方法上使用
@CachePut和@Cacheable注解通常是非常不可取的,因为它们有不同的行为。后者会使方法的调用因使用缓存而被跳过,而前者则是为了运行缓存更新而强制调用。
注解 @CacheEvict
@CacheEvict 标注在需要清除缓存的元素或类上面。当标注在一个类上面的时候,表示其中所有的方法都会触发缓存的清除操作。
@CacheEvict 具有一个额外的参数(allEntries),表示是否需要执行整个缓存的清除,而不仅仅是一个条目的清除(基于 key)。
@CacheEvict 的使用示例如下:
@CacheEvict(cacheNames="books", allEntries=true)
public void deleteBooks(long id) {...}
2万+

被折叠的 条评论
为什么被折叠?



