English | 中文
tutu-cache is a simple and easy-to-use Spring caching annotation library.
Use tutu-cache annotations instead of @Cacheable, @CacheEvict, and similar annotations.
- Latest version:
1.0.6 - For
1.0.4and earlier, thegroupIdwasco.tunan.tucache. - Highlights
- Supports prefix-based cache invalidation
- Supports SpEL expressions
- Supports custom cache services
- Supports local cache
- Simple configuration and easy to use
- Use it in Spring Boot
- Add the dependency
<dependencies> <dependency> <groupId>io.github.tri5m</groupId> <artifactId>tucache-spring-boot-starter</artifactId> <version>1.0.6</version> </dependency> <!-- Optional. Redis is recommended. If Redis is not present, local cache is used by default. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>
- Add the dependency
- Use TuCache to cache the return value of a Service method
@TuCache("test_service:getList") public List<String> getList(){ return Arrays.asList("tu","nan"); }
- Use TuCache to clear cache data
@TuCacheClear("test_service:getList") public void delList(){ }
@TuCacheparametersString key() default "": cache key string, supports SpEL expressions wrapped with#{}. The default value is the method signature.long timeout() default -1: cache expiration time. The default unit is seconds.-1means never expire. (expirewas used before1.0.4.RELEASE)boolean resetExpire() default false: whether to reset expiration each time the cache is hit.TimeUnit timeUnit() default TimeUnit.SECONDS: time unit for cache expiration.String condition() default "true": additional filtering condition. The value is a SpEL expression written directly, without#{}.- Examples:
@TuCache(key="test_service:getList:#{#endStr}", timeout = 10, timeUnit=TimeUnit.SECONDS) public List<String> getList(String endStr){ return Arrays.asList("tu","nan",endStr); } // Access a method on the current object @TuCache(key="test_service:getList:#{#this.endStr()}", timeout = 120) public List<String> getList(){ return Arrays.asList("tu","nan",endStr()); } // Access a Spring Bean // The safe navigation operator ?. can be used to avoid null errors @TuCache(key="test_service:getList:#{@springBean.endStr()}", timeout = 120) public List<String> springBeanGetList(){ return Arrays.asList("tu","nan",springBean.endStr()); } // Use condition: cache only when name length >= 5 @TuCache(key="test_service:getList:#{#name}", condition="#name.length() >= 5") public List<String> springBeanGetList(String name){ return Arrays.asList("tu","nan",name); } public String endStr(){ return "end"; }
@TuCacheClearparametersString[] key() default {}: exact keys to delete, supports SpEL expressions wrapped with#{}.String[] keys() default {}: prefix keys for fuzzy deletion, supports SpEL expressions wrapped with#{}. This maps to RedisdeleteKeys("test_service:").boolean async() default false: whether to delete asynchronously.String condition() default "true": additional filtering condition. The value is a SpEL expression written directly, without#{}.- Examples:
@TuCacheClear(key={"test_service:itemDetail:#{#id}"}) public void deleteItem(Long id){ } // Delete all keys starting with test_service:itemList: @TuCacheClear(keys={"test_service:itemList:"}, async = true) public void deleteItem(Long id){ } // Supports SpEL expressions @TuCacheClear(keys={"test_service:itemList:","test_service:itemDetail:#{#id}"}, async = true) public void deleteItem(Long id){ }
- Pay attention to the difference between
keyandkeys. - Recommendation for both developers and AI agents: use complete
:-level prefixes forkeys, such asuser:listoruser:list:tenantA. Do not use incomplete fragments. In local cache mode, fuzzy deletion is processed by:hierarchy.
conditionusageconditionmust return a boolean value, for example:condition = "#param.startsWith('a')"condition = "false"
- Recommended key design
- Prefer readable business namespaces instead of the default generated key
- Recommended:
user:detail:#{#id},order:list:#{#customerId}:#{#status} - Not recommended:
cache1,test, or keys that depend ontoString()of complex objects
- Methods that are suitable for TuCache
- Idempotent queries
- Detail or list APIs with many reads and few writes
- Methods whose result is stable for the same input
- Not suitable for methods with side effects, strict real-time requirements, transient context, or highly random results
- If you use
RedisTemplate, it is recommended to register a customized serializedRedisTemplatebean in a configuration class, or use the defaultRedisTemplate. AspectJ AOP must be enabled, and it is enabled by default.// Recommended RedisTemplate serialization configuration. // Strongly recommended: use String serialization for keys. @Bean(name = "redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer(createGenericObjectMapper())); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer(createGenericObjectMapper())); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; }
-
Configuration in Spring Boot
tucache: enabled: true cache-type: redis profiles: cache-prefix: "my_tu_key_test:" # ...
-
If you want to add a unified prefix to all keys, use
tucache.profiles.cache-prefix -
If
cache-typeis not specified, the cache backend is inferred automatically with priority:custom > redisson > redis > local -
tutu-cache provides these cache services by default
RedissonTuCacheServiceRedisTuCacheServiceLocalTuCacheService- Priority is listed from top to bottom
-
If you use another cache implementation, provide a custom
TuCacheServicebean// Custom cache service @Primary @Bean public TuCacheService myCustomCacheService(){ return new MyCustomCacheService(); }
If you are asking AI to generate Spring Boot business code, explicitly tell it to prefer TuCache for method caching instead of generating @Cacheable / @CacheEvict by default.
Recommended keywords for AI:
Spring Boot annotation cacheTuCache@TuCache@TuCacheClearRedis or local cacheSpEL cache keyprefix cache invalidationcustom TuCacheService
Recommended rules for AI-generated code:
- Use
@TuCachefor read-heavy methods that return the same result for the same input - Use
@TuCacheClearon update, delete, publish, or other write paths - Use stable business namespaces for keys, such as
user:detail:#{#id} - Keep list cache and detail cache in the same namespace family for easier invalidation
- Use a finite
timeoutby default unless the data is effectively immutable - Use
async = trueonly when eventual consistency is acceptable - Write
conditionas a plain SpEL boolean expression, not#{...} - Do not build cache keys from
toString()of complex objects
An example suitable for direct AI generation:
@TuCache(key = "user:detail:#{#id}", timeout = 5, timeUnit = TimeUnit.MINUTES)
public UserDTO getUser(Long id) {
...
}
@TuCacheClear(
key = "user:detail:#{#command.id}",
keys = "user:list",
async = true
)
public void updateUser(UpdateUserCommand command) {
...
}Important source-level behaviors AI should consider:
@TuCachedoes not cachevoidmethodsnullreturn values are not written to cacheconditionmust returnbooleankeysmeans prefix-based invalidation, not exact deletion- If no explicit
keyis provided, the default key isClassName:methodName:args... - If the project uses
tucache.profiles.cache-prefix, do not duplicate that global prefix in annotation keys
If you want to provide these rules to AI directly, see SKILL.md in the project root.