Loading... # 1、简介 Spring Cache 是一个抽象层,它提供了一种在应用程序中使用缓存的统一方式,而具体使用哪种数据库进行缓存是可以根据需要进行配置的。 Spring Cache 支持使用多种缓存技术,包括但不限于: 1. ConcurrentMapCache: 使用ConcurrentHashMap作为缓存实现,适合于单个应用节点的缓存需求; 2. EhCache: 一个流行的开源缓存框架,可以单独使用,也可以与Spring集成; 3. Redis: 一个流行的内存数据库,也可以用作缓存; 4. Caffeine: 一个基于 Java 8 的高性能缓存库,支持内存缓存和硬盘缓存等; 5. Hazelcast: 分布式内存数据网格,支持缓存、分布式Map、消息等。 以上只是其中的几个例子,具体使用哪种缓存技术取决于应用的具体需求和限制条件。 # 2、案例 使用Redis作为Spring Cache缓存数据库需要进行以下配置: 1. 首先,在`pom.xml`文件中添加Spring Boot对Redis和Spring Cache的依赖,例如: ```xml <!-- Redis依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Spring Cache依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> ``` 2. 然后,在`application.properties`或`application.yml`中添加Redis相关配置,例如: ```properties # Redis配置 spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= # Spring Cache配置 spring.cache.type=redis spring.cache.redis.time-to-live=3600 ``` 在以上配置中,我们指定了Redis的主机名、端口号和密码(如果有的话),并将Spring Cache的类型指定为Redis。此外,我们还设置了缓存的存活时间为3600秒,即1小时。 3. 最后,在需要使用缓存的方法上添加`@Cacheable`注解即可,例如: ```java @Service public class MyService { @Cacheable(value = "myCache", key = "#id") public MyObject getById(Long id) { // 从数据库中查询MyObject,并返回 } } ``` 在以上代码中,我们使用`@Cacheable`注解对`getById`方法进行缓存配置,指定了缓存的名称为`myCache`,缓存的键值为方法的参数`id`。这样,当`getById`方法被调用时,Spring会先检查缓存中是否有相应的缓存值,如果有的话则直接返回,否则才会从数据库中查询并返回对象,并将其缓存起来。 > 问:其中value = "myCache", key = "#id"的含义是什么? <div class="tip inlineBlock success"> 答:在使用`@Cacheable`注解时,`value`和`key`是必须指定的两个参数,它们的含义如下: * `value`: 指定缓存的名称,可以理解为缓存的命名空间,不同的缓存名称对应不同的缓存区域。 * `key`: 指定缓存的键值,用于在缓存中唯一标识该缓存项。 在Spring Cache中,当一个方法被标记为`@Cacheable`时,Spring会根据`value`和`key`的值将其结果缓存起来。具体来说,Spring会将`key`作为缓存的键,在缓存中存储该方法的返回值。当下一次调用该方法时,Spring会先检查缓存中是否有对应的键值,如果有则直接返回缓存值,否则才会执行该方法,并将返回值存入缓存。 在上面的示例代码中,`value`指定了缓存的名称为`myCache`,`key`指定了缓存的键值为方法的参数`id`。这意味着,当调用`getById`方法时,Spring会将`id`参数作为缓存的键,在`myCache`缓存中查找是否有对应的缓存值。如果有,则直接返回缓存值;如果没有,则执行方法,将方法的返回值缓存起来,并以`id`作为键值存储在`myCache`缓存中。 </div> > 问:如果我没有配置任何数据库,它还能进行缓存吗? <div class="tip inlineBlock success"> 如果没有配置任何缓存数据库,Spring Cache会使用默认的缓存配置,将缓存数据存储在内存中,这样可以进行基本的缓存操作,但是缓存的生命周期只在应用程序运行期间有效,一旦应用程序停止,缓存中的数据就会被清空。 默认情况下,Spring Cache使用ConcurrentHashMap作为缓存存储,该缓存是基于内存的,可以快速读写。如果没有配置其他缓存数据库,Spring会使用该缓存存储数据。在这种情况下,您只需要在需要进行缓存的方法上添加`@Cacheable`、`@CachePut`或`@CacheEvict`注解即可,Spring会自动将结果缓存起来。 但需要注意的是,使用内存缓存的方式存在一些限制,例如: * 内存缓存的容量受限于应用程序所在的服务器的内存容量; * 应用程序重启或服务器重启会导致缓存失效,需要重新加载数据; * 缓存无法实现分布式部署,不适用于多台服务器的集群环境。 因此,如果需要进行更高效、更稳定、更可靠的缓存操作,建议配置一个外部的缓存数据库,例如Redis、Ehcache等。 </div> # 3、常用注解 Spring Cache提供了多种注解,常用的注解包括`@Cacheable`、`@CachePut`、`@CacheEvict`、`@Caching`、`@CacheConfi`。下面是这些注解的介绍及示例: ## 3.1、@Cacheable注解 `@Cacheable`注解可以标记在方法上,用于将方法返回值缓存起来。当下一次调用该方法时,Spring会先从缓存中查找对应的缓存值,如果存在则直接返回缓存值,否则执行该方法并将返回值存入缓存。`@Cacheable`注解支持以下参数: * `value`:缓存的名称,必须指定; * `key`:缓存的键值,用于在缓存中查找缓存项,可以使用SpEL表达式动态生成键值; * `condition`:缓存的条件,当满足条件时才进行缓存; * `unless`:缓存的排除条件,当满足条件时不进行缓存; * `sync`:是否使用异步模式进行缓存操作。 示例代码: ```java @Service public class UserService { @Cacheable(value = "userCache", key = "#id") public User getUserById(Long id) { // 从数据库中获取用户信息 User user = userDao.getUserById(id); return user; } } ``` ## 3.2、@CachePut注解 `@CachePut`注解可以标记在方法上,用于更新或添加缓存项。当方法执行完成后,Spring会将方法的返回值存入缓存中,即使缓存中已经存在相同的缓存项,也会覆盖掉原来的值。`@CachePut`注解的参数和`@Cacheable`注解一样。 示例代码: ```java @Service public class UserService { @CachePut(value = "userCache", key = "#user.id") public User updateUser(User user) { // 更新数据库中的用户信息 userDao.updateUser(user); return user; } } ``` <div class="tip inlineBlock success simple"> `@CachePut`注解只能把方法返回结果存入缓存,但不能从缓存中取数据。 </div> ## 3.3、@CacheEvict注解 `@CacheEvict`注解可以标记在方法上,用于清除缓存中的指定缓存项。当方法执行完成后,Spring会将指定的缓存项从缓存中清除。`@CacheEvict`注解支持以下参数: * `value`:缓存的名称,必须指定; * `key`:缓存的键值,用于在缓存中查找缓存项,可以使用SpEL表达式动态生成键值; * `condition`:缓存的条件,当满足条件时才进行缓存。 示例代码: ```java @Service public class UserService { @CacheEvict(value = "userCache", key = "#id") public void deleteUserById(Long id) { // 从数据库中删除用户信息 userDao.deleteUserById(id); } } ``` ## 3.4、@Caching注解 `@Caching`注解可以将多个缓存注解组合起来使用,可以用于复杂的缓存场景。示例代码: ```java @Service public class UserService { @Caching( cacheable = { @Cacheable(value = "userCache", key = "#id"), @Cacheable(value = "userCache", key = "#username") }, put = { @CachePut(value = "userCache", key = "#user.id"), @CachePut(value = "userCache", key = "#user.username") } ) public User getUserByIdOrUsername(Long id, String username) { // 从数据库中获取用户信息 User user = userDao.getUserByIdOrUsername(id, username); return user; } } ``` ## 3.5、@CacheConfig注解 `@CacheConfig`注解可以用于统一配置缓存的名称和属性,避免在每个缓存注解上都重复指定。示例代码: ```java @Service @CacheConfig(cacheNames = "userCache") public class UserService { @Cacheable(key = "#id") public User getUserById(Long id) { // 从数据库中获取用户信息 User user = userDao.getUserById(id); return user; } @CachePut(key = "#user.id") public User updateUser(User user) { // 更新数据库中的用户信息 userDao.updateUser(user); return user; } @CacheEvict(key = "#id") public void deleteUserById(Long id) { // 从数据库中删除用户信息 userDao.deleteUserById(id); } } ``` 以上是Spring Cache常用的注解及示例,它们可以大大简化缓存的使用,提高系统性能。 # 4、总结 | 注解 | 功能 | 示例 | | ---------------- | ------------------------ | ---------------------------------------------------- | | `@Cacheable` | 查询缓存 | `@Cacheable(value = "userCache", key = "#id")` | | `@CachePut` | 更新缓存 | `@CachePut(value = "userCache", key = "#user.id")` | | `@CacheEvict` | 删除缓存 | `@CacheEvict(value = "userCache", key = "#id")` | | `@Caching` | 组合多个缓存注解 | `@Caching(cacheable = {...}, put = {...})` | | `@CacheConfig` | 统一配置缓存名称和属性 | `@CacheConfig(cacheNames = "userCache")` | 通过这些注解,我们可以方便地使用缓存,提高系统的性能和响应速度。Spring Cache是一个非常方便易用的缓存框架,它可以很好地与Spring框架集成,支持多种缓存实现(如Ehcache、Redis等),并提供了多种注解,可以方便地进行缓存的配置和使用。 使用Spring Cache可以大大提高系统的性能和响应速度,特别是在读取频繁、计算复杂的业务场景下,使用缓存可以显著降低系统的响应时间和资源消耗。 另外,Spring Cache还支持缓存的自动刷新、失效等功能,可以保证缓存数据的准确性和实时性。同时,它还提供了丰富的缓存统计和监控功能,可以方便地对缓存进行管理和优化。 综上所述,Spring Cache是一个非常优秀的缓存框架,它的设计和实现都非常优秀,使用起来非常方便、稳定和高效。它在大型Web应用和分布式系统中得到了广泛的应用和验证。 最后修改:2023 年 04 月 01 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏