Terminal 4.

Cache

2025/12/28
loading

cache,cash

Spring Cache

Springboot里写过一点:Spring Boot · Terminal 4

1
2
3
4
5
6
7
8
9
10
@Cacheable / @CachePut / @CacheEvict

CacheInterceptor (AOP 拦截)

CacheManager (缓存管理器)

Cache (具体缓存)

Redis / Caffeine / Ehcache

cacheNames可以理解为缓存key的前缀,可以为组件缓存的key变量;

当key不设置时,使用方法参数来初始化,注意key为SpEL表达式,因此如果要写字符串时,用单引号括起来

一个简单的使用姿势

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 首先从缓存中查,查到之后,直接返回缓存数据;否则执行方法,并将结果缓存
* <p>
* redisKey: cacheNames + key 组合而成 --> 支持SpEL
* redisValue: 返回结果
*
* @param name
* @return
*/
@Cacheable(cacheNames = "say", key = "'p_'+ #name")
public String sayHello(String name) {
return "hello+" + name + "-->" + UUID.randomUUID().toString();
}

还有condition设置,这个表示当它设置的条件达成时,才写入缓存

1
2
3
4
5
6
7
8
9
10
/**
* 满足condition条件的才写入缓存
*
* @param age
* @return
*/
@Cacheable(cacheNames = "condition", key = "#age", condition = "#age % 2 == 0")
public String setByCondition(int age) {
return "condition:" + age + "-->" + UUID.randomUUID().toString();
}

unless参数,从名字上可以看出它表示不满足条件时才写入缓存

@Caching

在实际的工作中,经常会遇到一个数据变动,更新多个缓存的场景,对于这个场景,可以通过@Caching来实现

1
2
3
4
5
6
7
8
9
10
/**
* caching实现组合,添加缓存,并失效其他的缓存
*
* @param age
* @return
*/
@Caching(cacheable = @Cacheable(cacheNames = "caching", key = "#age"), evict = @CacheEvict(cacheNames = "t4", key = "#age"))
public String caching(int age) {
return "caching: " + age + "-->" + UUID.randomUUID().toString();
}

@CacheConfig

当一个Service内的所有缓存方法的cacheNames都是同一个时,或者cacheManager都相同时,可以考虑在类上添加注解

1
2
3
4
5
@Service
@CacheConfig(cacheNames = "customCache", cacheManager = "customCacheManager")
public class AnoCacheService {
// ...
}

Gauva

Guava 是 Google 开源的一款 Java 工具库,提供了一些 JDK 没有或者增强 JDK 的个功能,Cache只是其中的一部分功能而已。

Cache Builder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 创建一个 CacheBuilder 对象
CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder()
.maximumSize(100) // 最大缓存条目数
.expireAfterAccess(30, TimeUnit.MINUTES) // 缓存项在指定时间内没有被访问就过期
.recordStats(); // 开启统计功能

// 构建一个 LoadingCache 对象
LoadingCache<String, String> cache = cacheBuilder.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return "技术派 value:" + key; // 当缓存中没有值时,加载对应的值并返回
}
});

// 存入缓存
cache.put("itwanger", "沉默王二");

// 从缓存中获取值
// put 过
System.out.println(cache.get("itwanger"));
// 没 put 过
System.out.println(cache.get("paicoding"));

// 打印缓存的命中率等统计信息
System.out.println(cache.stats());

LoadingCache 是一种特殊的 Cache,在缓存中不存在某个 key 的值时,可以通过 CacheLoader 来加载该 key 对应的值,并将其加入到缓存中。

CacheLoader 是 Guava 缓存库中的一个接口,用于在缓存未命中时加载缓存值。它定义了一个方法 load(K key),当缓存中没有 key 对应的值时,会调用该方法来获取该 key 对应的值并将其存入缓存中。

常用方法:

  1. newBuilder()

    该方法返回一个 CacheBuilder 实例,用于创建一个新的缓存实例。

  2. maximumSize(long maximumSize)

    该方法用于设置缓存的最大大小,以条目数为单位。如果缓存中的条目数超过了最大大小,则可能会触发缓存的回收策略,以释放一些缓存空间。

  3. expireAfterWrite(long duration, TimeUnit unit)

    该方法用于设置缓存的过期时间。在缓存中存储的每个条目被创建或者更新后,经过指定的时间后,该条目将被自动删除。可以使用 TimeUnit 枚举类型中的常量来指定时间单位,比如 TimeUnit.SECONDS、TimeUnit.MINUTES 等。

  4. expireAfterAccess(long duration, TimeUnit unit)

    该方法和 expireAfterWrite 方法类似,不同的是,该方法用于设置缓存中每个条目的最大闲置时间。如果一个条目在指定的时间内没有被访问,则该条目将被自动删除。

  5. stats()

    该方法用于启用缓存统计功能,可以用于监控缓存的使用情况。

  6. build()

    该方法用于创建和返回一个新的缓存实例。在调用该方法之前,需要进行一些其他的配置,比如设置缓存的最大大小、过期时间等。

CATALOG
  1. 1. Spring Cache
    1. 1.1. @Caching
    2. 1.2. @CacheConfig
  2. 2. Gauva
    1. 2.1. Cache Builder