Spring Cache 介绍

本文介绍了Spring Cache对缓存使用的抽象,可让现有代码不侵入业务代码就支持缓存。先说明了启动缓存的方法,接着详细阐述使用@Cacheable、@CacheEvict等注解声明缓存,还介绍了在缓存时通过输入、输出参数方式增加条件判断,最后进行了总结。

Spring Cache是对缓存使用的抽象,通过它我们可以在不侵入业务代码的基础上让现有代码即刻支持缓存。为现有的Spring 应用添加Cache非常简单,为了启用缓存,Spring充分利用了注释,就像启用框架中的任何其他配置级功能一样。

1 启动缓存

只需将@EnableCaching注解添加到任何配置类,即可以声明方式启用高速缓存功能:

@Configuration
@EnableCaching
public class CachingConfig {
 
    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("addresses");
    }
}

当然,您也可以使用XML配置启用缓存管理:

<beans>
    <cache:annotation-driven />
 
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean
                  class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
                  name="addresses"/>
            </set>
        </property>
    </bean>
</beans>

注意:在我们启用缓存之后 - 为了最小化设置 - 我们必须注册一个cacheManager。

使用XML可以使用更灵活的选项来配置缓存 - 您可以指定自己的缓存管理器,缓存解析器,错误处理程序,并且通常使用更高级的自定义选项。

2 使用注解来声明缓存

一旦启用了缓存,下一步就是将缓存行为绑定到具有声明性注解的方法。

2.1 @Cacheable

为方法启用缓存行为的最简单方法是使用@Cacheable对其进行声明,使用将存储结果的缓存名称对其进行参数化:

@Cacheable("addresses")
public String getAddress(Customer customer) {...}

方法被调用时,先从缓存中读取数据,如果缓存没有找到数据,再调用方法获取数据,然后把数据添加到缓存中

2.2 @CacheEvict

缓存可以变得非常大,我们可能会持续存储大量过时或未使用的数据。
@CacheEvict注解用于去除一个、多个或所有的缓存值-让新鲜值可以重新加载到缓存中:

@CacheEvict(value="addresses", allEntries=true)
public String getAddress(Customer customer) {...}

在这里,我们将附加参数allEntries与要清空的缓存结合使用 - 清除缓存地址中的所有条目并为新数据做好准备。

2.3 @CachePut

虽然@CacheEvict通过删除过时和未使用的条目来减少在大型缓存中查找条目的开销,但有些情况下,您希望避免从缓存中驱逐太多数据。您需要在更改条目时有选择地智能地更新条目。

使用@CachePut,您可以更新缓存的内容,而不会干扰方法执行。也就是说,调用方法时会自动把相应的数据放入缓存。

@CachePut(value="addresses")
public String getAddress(Customer customer) {...}

2.4 @Caching

如果要使用相同类型的多个注解来缓存方法,该怎么办?看下面的例子:

@CacheEvict("addresses")
@CacheEvict(value="directory", key=customer.name)
public String getAddress(Customer customer) {...}

上面的代码将无法编译,因为Java不允许为给定方法声明相同类型的多个注解。

上述问题的解决方法是:

@Caching(evict = { 
  @CacheEvict("addresses"), 
  @CacheEvict(value="directory", key="#customer.name") })
public String getAddress(Customer customer) {...}

如上面的代码片段所示,您可以使用@Caching对多个缓存进行分组,并使用它来实现您自己的自定义缓存逻辑。

2.5 @CacheConfig

使用@CacheConfig注解,您可以将一些缓存配置简化在类级别上 - 这样您就不必多次声明:

@CacheConfig(cacheNames={"addresses"})
public class CustomerDataService {
 
    @Cacheable
    public String getAddress(Customer customer) {...}

3 缓存时增加条件判断

3.1 输入参数方式

如果我们想要更多地控制注解何时处于活动状态,比如可以使用条件参数对@CachePut进行参数化,该参数采用SpEL表达式来缓存结果:

@CachePut(value="addresses", condition="#customer.name=='Tom'")
public String getAddress(Customer customer) {...}

3.2 输出参数方式

我们还可以根据方法的输出而不是输入来控制缓存- 通过unless参数:

@CachePut(value="addresses", unless="#result.length()<64")
public String getAddress(Customer customer) {...}

上述代码将缓存addresses,除非它们长度小于64个字符。

4 总结

在本文中,我们讨论了Spring中缓存的基础知识以及如何通过注解来充分利用该抽象。

### **Spring Cache 简介** **Spring Cache** 是 Spring 框架提供的一套 **缓存抽象层**,允许开发者通过注解的方式轻松集成多种缓存技术(如 Redis、Ehcache、Caffeine 等),无需关心底层缓存实现细节。 --- ### **1. 核心特性** | 特性 | 说明 | |---------------------|----------------------------------------------------------------------| | **注解驱动** | 通过 `@Cacheable`、`@CacheEvict` 等注解声明缓存逻辑 | | **多缓存支持** | 兼容 Redis、Ehcache、Caffeine、Guava Cache 等 | | **SpEL 表达式** | 支持动态生成缓存 Key(如 `#user.id`) | | **条件缓存** | 可设置条件(如 `@Cacheable(unless="#result == null")`) | | **自动序列化** | 与 Redis 集成时自动处理对象序列化/反序列化 | --- ### **2. 常用注解** #### **① `@Cacheable`(缓存查询)** ```java @Cacheable(value = "users", key = "#id") public User getUserById(Long id) { return userRepository.findById(id); // 方法返回结果自动缓存 } ``` - **`value`/`cacheNames`**:指定缓存名称(如 Redis 的 Key 前缀) - **`key`**:自定义缓存 Key(支持 SpEL) #### **② `@CachePut`(更新缓存)** ```java @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { return userRepository.save(user); // 更新数据库并同步缓存 } ``` #### **③ `@CacheEvict`(删除缓存)** ```java @CacheEvict(value = "users", key = "#id") public void deleteUser(Long id) { userRepository.deleteById(id); // 删除数据库记录并清除缓存 } ``` - **`allEntries`**:是否清空整个缓存区域(如 `@CacheEvict(allEntries = true)`) #### **④ `@Caching`(组合操作)** ```java @Caching( evict = {@CacheEvict("users"), @CacheEvict(value = "orders", key = "#userId")} ) public void clearUserCache(Long userId) { ... } ``` --- ### **3. 集成 Redis 示例** #### **步骤 1:添加依赖** ```xml <!-- Spring Boot Starter Cache + Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` #### **步骤 2:配置 Redis** ```yaml # application.yml spring: cache: type: redis redis: host: localhost port: 6379 ``` #### **步骤 3:启用缓存** ```java @SpringBootApplication @EnableCaching // 开启缓存功能 public class MyApp { ... } ``` --- ### **4. 高级功能** #### **自定义 Key 生成器** ```java @Bean public KeyGenerator customKeyGenerator() { return (target, method, params) -> method.getName() + "_" + Arrays.toString(params); } // 使用示例 @Cacheable(value = "users", keyGenerator = "customKeyGenerator") ``` #### **条件缓存** ```java @Cacheable(value = "users", condition = "#id > 10") // 仅当 id > 10 时缓存 public User getUserIf(Long id) { ... } ``` #### **TTL 配置** ```yaml spring: cache: redis: time-to-live: 30m # 全局默认 30 分钟过期 ``` --- ### **5. 注意事项** 1. **缓存穿透**:对 `null` 结果加缓存(如 `unless="#result == null"`) 2. **缓存雪崩**:为不同 Key 设置随机 TTL 3. **一致性**:数据库更新后需同步清理缓存(如 `@CacheEvict`) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

peterwanghao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值