Spring 支持基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。
public class PigxClientDetailsService extends JdbcClientDetailsService { @Cacheable(value = SecurityConstants.CLIENT_DETAILS_KEY, key = "#clientId") public ClientDetails loadClientByClientId(String clientId) { return super.loadClientByClientId(clientId); } }}
@Slf4j public class RedisAutoCacheManager extends RedisCacheManager { /** * 从上下文中获取租户ID,重写@Cacheable value 值 * @param name * @return */ @Override public Cache getCache(String name) { return super.getCache(TenantContextHolder.getTenantId() + StrUtil.COLON + name); } }
在GUI 工具中,会通过':'的分隔符,进行分组,展示效果会更好
public @interface Cacheable { @AliasFor("cacheNames") String[] value() default {}; @AliasFor("value") String[] cacheNames() default {}; String key() default ""; String keyGenerator() default ""; String cacheManager() default ""; String cacheResolver() default ""; String condition() default ""; String unless() default ""; boolean sync() default false; }
@Service @AllArgsConstructor public class PigXMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService { private final SysRoleMenuMapper sysRoleMenuMapper; @Override @Cacheable(value = "menu_details#2000", key = "#roleId + '_menu'") public List<MenuVO> findMenuByRoleId(Integer roleId) { return baseMapper.listMenusByRoleId(roleId); } }
public class RedisAutoCacheManager extends RedisCacheManager { private static final String SPLIT_FLAG = "#"; private static final int CACHE_LENGTH = 2; @Override protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) { if (StrUtil.isBlank(name) || !name.contains(SPLIT_FLAG)) { return super.createRedisCache(name, cacheConfig); } String[] cacheArray = name.split(SPLIT_FLAG); if (cacheArray.length < CACHE_LENGTH) { return super.createRedisCache(name, cacheConfig); } if (cacheConfig != null) { long cacheAge = Long.parseLong(cacheArray[1]); cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(cacheAge)); } return super.createRedisCache(name, cacheConfig); } }
@Override public void put(Object key, @Nullable Object value) { Object cacheValue = preProcessCacheValue(value); if (!isAllowNullValues() && cacheValue == null) { throw new IllegalArgumentException(String.format( "Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=/"#result == null/")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.", name)); } cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl()); }