在 Spring 中,使用缓存通常涉及以下步骤:
1、添加缓存依赖: 确保项目中添加了缓存相关的依赖。如果使用 Maven,可以在项目的 pom.xml 文件中添加 Spring Cache 的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、配置缓存: 在 Spring 配置文件中进行缓存的基本配置。如果是使用 Spring Boot,通常无需额外配置,因为 Spring Boot 提供了默认的缓存配置。
第1步:在启动类上加注解@EnableCaching
第2步:在具体方法上加注解【@CachePut、@CacheEvict、@Caching】或者在方法上添加 @Cacheable 注解: 在需要缓存的方法上使用 @Cacheable 注解,指定缓存的名称、键等信息。
3、触发缓存: 调用带有 @Cacheable 注解的方法时,Spring 会检查缓存中是否已经有了相应的结果。如果有,则直接返回缓存结果;如果没有,则执行方法体,计算结果并将结果缓存起来。
1、@Cacheable
@Cacheable 是 Spring Framework 中的一个注解,用于声明某个方法的结果应该被缓存,以便在后续调用中可以直接返回缓存的结果,而不需要再次执行方法体。这个注解通常用于提高方法的执行效率,尤其是对于那些计算成本较高的方法。
基本用法
import org.springframework.cache.annotation.Cacheable;
public class MyService {
@Cacheable(value = "myCache", key = "#input")
public String getResult(String input) {
// 如果缓存中存在以input为key的结果,则直接返回缓存结果
// 否则,执行方法体,并将结果缓存起来
// ...
}
}
在上述例子中:
@Cacheable 注解标注在 getResult 方法上,表示该方法的结果将会被缓存。
value 属性指定了缓存的名称(可以有多个缓存,每个缓存有一个名称)。
key 属性指定了缓存的键,这里使用了 SpEL(Spring Expression Language)表达式,表示使用 input 参数的值作为缓存的键。有时候会按照下方书写方式:
@Cacheable(value = "myCache", key = "#p0+','+#p1")
key = “#p0+‘,’+#p1” :指定缓存的键,使用了 Spring Expression Language(SpEL)的语法。#p0 表示方法的第一个参数,#p1 表示方法的第二个参数。在这个例子中,键由第一个参数和第二个参数以逗号连接而成。这意味着如果两次调用方法的时候,这两个参数的值相同,那么它们会共享相同的缓存结果。如果想要每次调用方法都修改缓存值,可以用其他拼接符连接,比如横杠、空格、冒号或者将方法名作为key值一部分。
key = "#p0 + '_' + #p1" // 使用下划线
key = "#p0 + ',' + #p1 + ',' + #p2" // 添加额外的参数或常量
key = "methodName + ',' + #p0 + ',' + #p1" //使用方法名作为一部分
注意事项:
@Cacheable 注解需要在 Spring 环境中生效,因此通常需要在 Spring 的配置文件中启用缓存功能。
方法的返回值类型应该是可序列化的,以便能够存储在缓存中。
缓存的键是根据 key 属性生成的,所以确保它能够唯一标识方法的输入参数。
@Cacheable 是 Spring Cache 抽象的一部分,而具体的缓存实现可以是基于不同的后端,比如基于内存、Redis、Ehcache 等。
我们在使用的时候常常会和@SqlQuery注解一块使用,如果一个方法同时使用了 @Cacheable 注解和 @SqlQuery 注解,那么其执行流程通常如下:
首次调用: 当方法被首次调用时,Spring 会先检查缓存(由 @Cacheable
注解管理)。如果缓存中存在对应的结果,则直接从缓存中取出并返回,而不会执行实际的 SQL 查询。
缓存未命中: 如果缓存中不存在对应的结果,那么方法体会被执行。在方法体中,可能会执行 SQL 查询(由 @SqlQuery
注解管理),并将查询结果映射为方法的返回类型。
结果缓存: 如果启用了 @Cacheable
注解,方法执行完毕后,计算得到的结果会被缓存起来,以便下次相同的方法调用可以直接从缓存中获取。
所以,如果缓存中已有相应的结果,实际的 SQL 查询可能不会执行。这样可以有效减轻对数据库的访问压力,提高方法的执行效率。在使用这两个注解时,确保缓存的键和 SQL 查询的参数不会引起混淆,以便正确地识别和管理缓存。
2、@CacheEvict
@CacheEvict 是 Spring 框架中用于清除缓存的注解。它用于标记一个方法,在方法执行时会清除指定缓存中的数据。以下是 @CacheEvict 注解的主要属性和用法:
主要属性:
value(或 cacheNames): 指定要清除的缓存的名称,可以是一个字符串数组。例如:@CacheEvict(value = “myCache”) 或 @CacheEvict(cacheNames = {“cache1”, “cache2”})。
key: 指定用于生成缓存键的 SpEL 表达式。例如:@CacheEvict(value = "myCache", key = "#userI
condition: 指定清除缓存的条件,是一个 SpEL 表达式,如果表达式的值为 false,则不会清除缓存。例如:@CacheEvict(value = "myCache", condition = "#userId > 0")。
allEntries: 如果设置为 true,则会清除指定缓存中的所有条目。例如:@CacheEvict(value = "myCache", allEntries = true)
。
beforeInvocation: 如果设置为 true,则在方法调用之前清除缓存;如果设置为 false(默认),则在方法调用之后清除缓存。例如:@CacheEvict(value = "myCache", beforeInvocation = true)
。
示例用法:
@Service
public class MyService {
@CacheEvict(value = "myCache", key = "#userId")
public void clearCacheByUserId(long userId) {
// 此方法执行时,会清除名为 "myCache" 中 key 为 userId 的缓存条目
}
@CacheEvict(value = "myCache", allEntries = true)
public void clearEntireCache() {
// 此方法执行时,会清除名为 "myCache" 中的所有缓存条目
}
}
在上述例子中,clearCacheByUserId 方法用于清除名为 “myCache” 中 key 为 userId 的缓存条目,而 clearEntireCache 方法用于清除 “myCache” 中的所有缓存条目。
请注意,@CacheEvict 注解通常用于在方法执行时清除缓存。如果方法执行抛出异常,缓存清除可能不会发生,除非设置了 beforeInvocation = true。因此,要确保清除缓存的操作是安全的,不会因为异常而导致缓存清除失败。
3、@CachePut
@CachePut 是 Spring 框架中用于更新缓存的注解。它用于标记一个方法,在方法执行时会将结果放入缓存中。与 @Cacheable 不同,@CachePut 不会先检查缓存中是否已有结果,而是直接将方法的返回值放入缓存中。
以下是 @CachePut 注解的主要属性和用法:
主要属性:
value(或 cacheNames): 指定要更新的缓存的名称,可以是一个字符串数组。例如:@CachePut(value = "myCache") 或 @CachePut(cacheNames = {"cache1", "cache2"})
。
key: 指定用于生成缓存键的 SpEL 表达式。例如:@CachePut(value = "myCache", key = "#userId")
。
condition: 指定放入缓存的条件,是一个 SpEL 表达式,如果表达式的值为 false,则不会放入缓存。例如:@CachePut(value = "myCache", condition = "#userId > 0")
。
unless: 与 condition 相反,如果表达式的值为 true,则不会放入缓存。例如:@CachePut(value = "myCache", unless = "#result == null")
。
示例用法:
@Service
public class MyService {
@CachePut(value = "myCache", key = "#userId")
public String updateCacheByUserId(long userId) {
// 此方法执行时,会将返回值放入名为 "myCache" 中 key 为 userId 的缓存条目
// 注意:不会先检查缓存中是否已有结果,直接将方法的返回值放入缓存中
// ...
return "Updated Value";
}
}
在上述例子中,updateCacheByUserId 方法用于将返回值放入名为 “myCache” 中 key 为 userId 的缓存条目。这个方法在执行时,不会先检查缓存中是否已有结果,而是直接将方法的返回值放入缓存中。
@CachePut 通常用于在更新操作之后,将最新的结果放入缓存,以保持缓存的一致性。需要注意的是,与 @Cacheable 不同,@CachePut 不会阻止方法的执行,即使缓存操作失败也不会影响方法的正常执行。
4、@Caching
@Caching 是 Spring 框架中用于组合多个缓存注解的注解。它允许同时在一个方法上使用多个缓存相关的注解,包括 @Cacheable、@CachePut、@CacheEvict 等,从而提供更灵活的缓存配置。
示例用法:
@Service
public class MyService {
@Caching(
cacheable = {@Cacheable(value = "cache1", key = "#userId")},
put = {@CachePut(value = "cache2", key = "#result.id")}
)
public User getUserById(long userId) {
// 先尝试从 "cache1" 缓存中获取结果
// 如果获取成功,则返回结果,不执行方法体
// 如果获取失败,则执行方法体,并将结果放入 "cache1" 和 "cache2" 缓存中
// ...
return new User(userId, "John Doe");
}
}
在上述例子中,@Caching 注解用于同时使用 @Cacheable 和 @CachePut 注解。具体来说:
@Cacheable 注解用于尝试从名为 “cache1” 的缓存中获取结果,如果获取成功,则直接返回结果,不执行方法体。
@CachePut 注解用于将方法的返回值放入名为 “cache2” 的缓存中,不论缓存中是否已有相同的键。
通过 @Caching 注解,可以更灵活地组合多个缓存注解,以满足复杂的缓存需求。
1、注解属性中设置
在使用 @Cacheable 注解时,你可以通过设置 expire 或 expireAfterWrite 属性来配置缓存的失效时间。这取决于使用的缓存管理器,因为不同的缓存管理器可能支持不同的配置。
例如,如果你使用的是 Spring Boot,并且底层的缓存管理器是基于 Caffeine 的,你可以使用 expireAfterWrite 属性来设置失效时间。以下是一个示例:
@Cacheable(value = "myCache", key = "#input", expireAfterWrite = 5, timeUnit = TimeUnit.MINUTES)
public String getResult(String input) {
// 如果缓存中存在以 input 为 key 的结果,则直接返回缓存结果
// 否则,执行方法体,并将结果缓存起来,缓存时间为 5 分钟
// ...
}
在上述示例中:
expireAfterWrite = 5 表示缓存项在写入后经过 5 分钟过期。
timeUnit = TimeUnit.MINUTES 表示时间单位是分钟。
具体的配置方式取决于使用的缓存管理器。如果你使用的是其他缓存管理器,例如 EhCache、Redis 等,具体的配置方式可能会有所不同。在配置文件或注解中查看相关属性,以确保正确地设置缓存的失效时间。
2、redis管理器设置
当使用 Redis 作为缓存管理器时,可以通过 Spring Boot 的配置文件或 Java 配置来设置 Redis 缓存的失效时间。以下是一个示例:
在 Spring Boot 的配置文件中设置 Redis 缓存失效时间: 在 application.properties 或
application.yml 文件中添加以下配置:
# Redis 服务器地址 spring.redis.host=localhost
# Redis 服务器端口 spring.redis.port=6379
# 缓存的默认失效时间,单位秒 spring.cache.redis.time-to-live=600
上述配置中的 spring.cache.redis.time-to-live
表示缓存的默认失效时间为600秒(10分钟)。这个值会应用于所有通过 @Cacheable、@CachePut 注解配置的缓存。
在 Java 配置中设置 Redis 缓存失效时间: 如果你使用 Java 配置类,可以在配置类中通过
RedisCacheConfiguration 来设置缓存的失效时间。以下是一个示例:
java @Configuration @EnableCaching public class CacheConfig
extends CachingConfigurerSupport {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600)); // 设置缓存失效时间为600秒(10分钟)
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
} }
在上述配置中,entryTtl(Duration.ofSeconds(600))
表示设置缓存的失效时间为600秒。这个值同样会应用于所有通过 @Cacheable、@CachePut 注解配置的缓存。
根据具体的需求,你可以根据缓存的特定性配置不同的失效时间。上述示例中仅作为演示,实际应用中可以根据业务需求来设置合适的缓存失效时间。