Skip to content

缓存应用

基本使用

@EnableCaching 开启缓存功能

1752977837097-eaea3f92-cb74-4bdd-b02f-0761ee2505de.png

@Cacheable 触发缓存储存

java
@Cacheable(cacheNames = "users", key = "#user.id")
public User save(User user) {
    return user;
}

@CacheEvict 触发缓存回收

java
@CacheEvict(cacheNames = "users", key = "#id")
public void delete(int id) {
}

@CachePut 更新缓存

java
@CachePut(cacheNames = "users", key = "#user.id")
public User update(User user) {
    return user;
}

@Caching 组合缓存操作

java
@Caching(evict = {
    @CacheEvict(cacheNames = "primary", key = "#p0"), // p0 表示第一个参数
    @CacheEvict(cacheNames = "secondary", key = "#id")
})
public void delete(String name, int id) {
}

@CacheConfig 类级共享缓存相关设置

高级应用

自定义注解

java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Cacheable(cacheNames = "users", key = "#user.id")
public @interface PackCache {
}

@PackCache
public User save(User user) {
    return user;
}

切换缓存实现

java
@Configuration
public class CacheConfig {

    @Bean
    public CacheManager memoryCacheManager() {
        return new ConcurrentMapCacheManager(); // 可以指定缓存名称列表
    }

    @Bean
    @Primary
    public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
        // 配置可参考 RedisCache 配置
        return RedisCacheManager.builder(connectionFactory).build(); 
    }

}

自定义缓存 key 及生成策略

java
@Cacheable(
    cacheNames = "users",
    key = "T(com.xyg.u1.order.cache.UserKeyGenerator).genKey(#user)", // SPEL
    cacheManager = "memoryCacheManager",
    keyGenerator = "userKeyGenerator" // 同时声明 key 和 generator, key 被忽略
)
public User save(User user) {
    return user;
}

@Component
public class UserKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object target, Method method, Object... params) {
        return target.hashCode() + Arrays.deepToString(params);
    }

    public String genKey(User user) {
        return user.toString();
    }

}

条件缓存

java
 @Cacheable(
    cacheNames = "users",
    condition = "#user.name != null && #user.name != ''" // name 属性不为空缓存
)
public User save(User user) {
    return user;
}

根据结果缓存

java
@Cacheable(
    cacheNames = "users",
    unless = "#result != null" // 结果为 null 不缓存
)
public User save(User user) {
    return user;
}

删除所有缓存

java
@CacheEvict(
    cacheNames = "users",
    key = "#id",
    allEntries = true // 清除缓存对象里的所有数据,若同时指定 key (key不生效)
)
public void delete(int id) {
}

自定义缓存解析器

java
@Component
public class PackCacheResolver implements CacheResolver {

    private final CacheManager cacheManager;

    public PackCacheResolver(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
        // 缓存注解(如 @Cacheable、@CacheEvict)中声明的 cacheNames 或 value 属性
        Collection<String> cacheNames = context.getOperation().getCacheNames();
        // 如果未配置缓存名称,返回空集合
        if (cacheNames == null || cacheNames.isEmpty()) {
            return Collections.emptyList();
        }
        // 遍历缓存名称,从 CacheManager 获取对应的 Cache 实例
        Collection<Cache> result = new ArrayList<>(cacheNames.size());
        for (String cacheName : cacheNames) {
            Cache cache = this.cacheManager.getCache(cacheName);
            if (cache == null) {
                // todo: 可扩展逻辑(如创建默认缓存或抛异常)
            }
            result.add(cache);  // 将找到的 Cache 加入结果集
        }

        return result; // 返回所有匹配的 Cache 实例
    }
}
java
@Cacheable(
    cacheNames = "users",
    cacheResolver = "packCacheResolver"
)
public User save(User user) {
    return user;
}

配置

Guava | Caffeine 配置

xml
<!-- Caffeine -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>

<!-- Guava (可选,Caffeine 性能更优) -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>
java
// ---------- Caffeine 配置 ----------
@Bean
public CacheManager caffeineCacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder()
        .initialCapacity(100)          // 初始容量
        .maximumSize(1000)            // 最大缓存数量
        .expireAfterWrite(10, TimeUnit.MINUTES)  // 写入后10分钟过期
        .recordStats());              // 开启统计
    return cacheManager;
}

// ---------- Guava 配置(可选) ----------
@Bean
public CacheManager guavaCacheManager() {
    GuavaCacheManager cacheManager = new GuavaCacheManager();
    cacheManager.setCacheBuilder(CacheBuilder.newBuilder()
        .maximumSize(1000)
        .expireAfterWrite(10, TimeUnit.MINUTES));
    return cacheManager;
}

Redis Cache 配置

xml
<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>
java
@Configuration
@EnableCaching // 启用缓存
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        RedisSerializer<Object> valueSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(valueSerializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(valueSerializer);

        template.afterPropertiesSet();
        return template;
    }
    
    // 配置 redis 缓存序列化
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        // GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); // 携带 @class
        RedisCacheConfiguration cacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofDays(1))   // 设置缓存过期时间为一天
                        .disableCachingNullValues()     // 禁用缓存空值,不缓存null校验
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
                                new Jackson2JsonRedisSerializer<>(Object.class)));     // 设置CacheManager的值序列化方式为json序列化,可加入@Class属性
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();     // 设置默认的cache组件
    }

}

更新: 2025-07-20 13:18:58
原文: https://www.yuque.com/lsxxyg/sz/txdnxhs4b4e281gs