必须加@enablecaching才能启用@cacheable,否则注解无效;需引入spring-boot-starter-cache依赖;key须用spel指定(如#id)并确保可序列化;redis序列化必须配置jackson等可读格式,避免二进制乱码。

@Cacheable 能用,但直接加就生效?别急——Spring Boot 默认不启用缓存抽象,@Cacheable 注解本身只是“声明”,没 @EnableCaching 就是废纸一张。
必须加 @EnableCaching 启用缓存功能
Spring 的缓存注解(@Cacheable、@CacheEvict 等)属于 AOP 增强,底层依赖 Spring Cache 抽象层。不显式启用,所有注解都会被忽略,方法照常执行,缓存压根不会写入 Redis。
- 加在主启动类上最稳妥:
@SpringBootApplication和@EnableCaching可共存 - 不要加在
@Configuration类里再用@Import引入——容易因配置加载顺序导致失效 - Spring Boot 3.x 中
spring-boot-starter-cache仍需显式引入(部分高版本 starter 不自动带),否则编译可能不报错但运行时无 AOP 代理
@Cacheable 的 key 必须可序列化且唯一
Redis 缓存键默认由 Spring 生成,格式为 cacheName:SimpleKey[]。如果方法参数含复杂对象(如自定义 DTO),SimpleKey 会调用 toString() 或反射拼接,极易冲突或乱码。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 强制指定
key:用 SpEL 表达式,比如@Cacheable(cacheNames="user", key="#id") - 避免用
#p0这类位置参数——重构方法签名后会 silently 失效 - 若参数是对象,用
key="#user.id"而非key="#user",后者默认序列化整个对象,体积大且不可读 - key 中禁止出现空格、特殊字符(如
/、{),Redis key 本质是字符串,非法字符会导致IllegalArgumentException
RedisTemplate 序列化配置直接影响缓存可读性
没配序列化?@Cacheable 写进 Redis 的 value 是一堆 \xac\xed\x00\x05... 二进制垃圾,连 redis-cli get xxx 都看不懂,排查问题全靠猜。
- 必须重置
RedisTemplate的valueSerializer:推荐Jackson2JsonRedisSerializer或GenericJackson2JsonRedisSerializer -
keySerializer和hashKeySerializer必须设为StringRedisSerializer,否则 cacheName + key 拼接后无法被正确识别 - 别用
JdkSerializationRedisSerializer(默认值)——它依赖类路径和 serialVersionUID,跨服务或升级后极易反序列化失败 - 如果用了 Lombok
@Data,确保实体类有无参构造器和 getter,否则 Jackson 序列化会抛InvalidDefinitionException
缓存穿透/击穿不是注解能解决的
@Cacheable 只管“有数据就缓存”,不管“没数据怎么办”。查数据库返回 null,它照样缓存 null——下次还走缓存,永远绕不开 DB,这就是缓存穿透。
- 空值缓存要手动做:
@Cacheable(unless="#result == null")不够,得配合@CachePut或业务逻辑写空对象(如new NullHolder()) - 热点 key 失效瞬间大量请求打穿缓存?
@Cacheable本身不提供锁或逻辑保护,得靠@Cacheable(sync=true)(仅限单机)或外置分布式锁 -
condition和unless是过滤开关,不是兜底方案:前者控制“要不要缓存”,后者控制“缓存什么”,都不改变 null 返回值本身










