# pop-cache **Repository Path**: billho/pop-cache ## Basic Information - **Project Name**: pop-cache - **Description**: PopCache 是一个 Spring Boot 启动器,提供基于 Redis 的缓存和分布式锁功能。它提供了一种简单灵活的方式将缓存和锁机制集成到 Spring Boot 应用中。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-02-08 - **Last Updated**: 2026-08-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: 缓存, Redis, Spring, SpringBoot ## README # PopCache > 用一行注解,取代一堆 Redis 模板代码。 基于 Redis 的 Spring Boot 注解式缓存与分布式锁启动器。 通过 `@Cache`、`@CacheClear`、`@GlobalLock` 三个注解,将缓存与锁的控制逻辑从业务代码中彻底剥离。 [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.5-green.svg)](https://spring.io/projects/spring-boot) [![Java](https://img.shields.io/badge/Java-17%2B-orange.svg)](https://openjdk.org/) [![Version](https://img.shields.io/badge/version-3.0.0-brightgreen.svg)](pom.xml) --- ## 为什么选择注解而不是手写 Redis 代码? **手写方式**(代码量大、容易遗漏、难以维护): ```java public UserDTO getUser(String userId) { String cacheKey = "user:" + userId; String cached = redisTemplate.opsForValue().get(cacheKey); if (cached != null) { return JSON.parseObject(cached, UserDTO.class); } UserDTO user = userRepository.findById(userId); if (user != null) { redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(user), 5, TimeUnit.MINUTES); } return user; } ``` **PopCache 注解方式**(一行,零侵入): ```java @Cache(key = "user:{1}", expireSeconds = 300) public UserDTO getUser(String userId) { return userRepository.findById(userId); } ``` 两者效果完全等价。**推荐始终优先使用注解**,除非业务需要在代码中动态控制缓存 key 或过期时间。 --- ## 快速开始 ### 第一步:添加依赖 ```xml cn.billho spring-boot-starter-pop-cache 3.0.0 ``` ### 第二步:配置 Redis 连接 ```yaml spring: application: name: my-service # 必须配置,用于缓存数据溯源 popcache: redis: host: 127.0.0.1 port: 6379 password: your_password # 无密码时留空 database: 0 enable: true ``` ### 第三步:在方法上加注解,完成 ```java @Service public class UserService { @Cache(key = "user:{1}", expireSeconds = 300) public UserDTO getUser(String userId) { return userRepository.findById(userId); // 仅首次调用执行 } @CacheClear(key = "user:{1}") public void updateUser(String userId, UserDTO dto) { userRepository.save(dto); // 执行后自动清除缓存 } } ``` 不需要注入 `RedisTemplate`,不需要手动序列化,不需要写任何 Redis 操作代码。 --- ## 注解速查 > 完整的参数说明、执行逻辑与代码示例请参阅 [LLMS.md](LLMS.md#注解完整规格与使用示例)。 | 注解 | 必填参数 | 可选参数 | 用途 | |------|---------|---------|------| | `@Cache` | `key` | `region`、`expireSeconds`(默认 720s) | 方法结果缓存,命中时直接返回,不执行原方法 | | `@CacheClear` | 无 | `key`、`region` | 方法执行后清除指定缓存;`key` 为空则清除整个 `region` | | `@GlobalLock` | `key` | `expireSeconds`(默认 15s) | 分布式互斥锁;获取失败静默返回零值 | **`region` 使用原则**:`region` 用于将同一类型的缓存聚合到一个 Redis Hash 中,便于批量管理。**`region` 应填静态名称(不含占位符),占位符放入 `key`**。不需要聚合管理时,直接用 `key`,无需填 `region`。 ```java // 无需聚合:直接用 key @Cache(key = "product:{1}", expireSeconds = 600) // 需要聚合:region 填静态名,参数放到 key @Cache(region = "user-cache", key = "{1}:profile", expireSeconds = 300) @CacheClear(region = "user-cache", key = "{1}:profile") // 删 field @CacheClear(region = "user-cache") // 删整个 Hash,所有用户缓存失效 ``` `key` 支持占位符 `{N}`(第 N 个参数)和 `{N.field}`(对象字段反射取值),索引从 **1** 开始。 --- ## 配置属性参考 ```yaml spring: application: name: your-service # 必须配置 popcache: redis: host: 127.0.0.1 # 必填,Redis 服务器地址 port: 6379 # 默认 6379 password: "" # 默认空(无密码) database: 13 # 默认 13 timeout: 2000 # 默认 2000(秒) enable: true # 默认 true;设为 false 可一键关闭所有缓存,直接执行原方法 ``` > `enable: false` 非常适合本地开发调试,无需启动 Redis 也能正常运行业务代码。 --- ## 扩展点 PopCache 的核心行为均通过接口抽象,只需注册对应 Bean 即可覆盖默认实现: | 扩展点 | 接口 | 典型场景 | |------|------|----------| | 自定义序列化 | `ISerialize` | 替换 FastJSON2 为 Jackson、Kryo 等 | | 自定义键生成 | `IKeyGenerate` | 加统一前缀、哈希冠名等 | | 自定义反序列化 | `IResultParse` | 支持自定义泛型解析逻辑 | > 完整实现代码参阅 [LLMS.md — 扩展接口说明](LLMS.md#扩展接口说明)。 --- ## 注意事项 1. **`spring.application.name` 必须配置**:应用名写入每条缓存记录的 `appName` 字段,用于多应用共用 Redis 时的数据追踪。 2. **方法返回 `null` 不缓存**:避免缓存空值导致后续调用误判。如需缓存空值,请自定义 `ISerialize`,以特殊占位符(如 `"__NULL__"`)表示 null 并在读取时还原。 3. **`@GlobalLock` 失败静默返回零值**:调用方须主动判断返回值,不可假设方法一定被执行。 4. **Region 过期粒度为整个 Hash**:同一 `region` 下所有 field 共享同一过期时间,设计 key 时避免将过期周期差异大的数据放入同一 region。 5. **`expireSeconds` 与锁持有时间的关系**:`@GlobalLock` 的 `expireSeconds` 是**最大**持有时间,正常流程中方法执行完毕后锁立即释放;该参数仅用于异常情况(如进程崩溃)的兜底超时。 --- ## 模块说明 | 模块 | Artifact ID | 说明 | |------|------------|------| | 核心实现 | `core` | Redis 操作、键生成、序列化,纯 Java,无 Spring 依赖 | | 注解定义 | `spring-boot-pop-cache-annotation` | `@Cache`、`@CacheClear`、`@GlobalLock` 定义 | | 自动配置 | `spring-boot-starter-pop-cache` | Spring Boot 自动配置、AOP 切面、属性绑定 | 通常只需引入 `spring-boot-starter-pop-cache`,其他模块作为传递依赖自动引入。 --- ## 环境要求 | 组件 | 最低版本 | |------|---------| | Java | 17 | | Spring Boot | 3.4.5 | | Redis | 4.0 | --- ## 贡献指南 1. Fork 本仓库 2. 从 `main` 创建功能分支:`git checkout -b feature/your-feature` 3. 提交并推送修改 4. 创建 Pull Request,说明改动动机 --- ## 许可证 本项目采用 [Apache License 2.0](LICENSE) 协议。