从注解的名字就可以看出该注解是一个缓存相关的注解, 在不引入分布式缓存(redis等)的前提下, spring 会默认提供一个缓存(本地缓存 CacheManager)提供使用.

缓存的应用场景

 高频词汇, 热点信息, 变化不大等等....的数据, 避免频繁的访问数据库

 相关注解

@Cacheable  主要是针对方法的配置,能够根据方法的求情参数对其结果进行缓存。

@CachePut    保证方法被调用,又希望结果被缓存 缓存更新

@CacheEvict  清空缓存  删除数据时的方法。

@EnableCaching  开启基于注解的缓存

使用方法

这里为了节省时间 只讲解@Cacheable的使用, 其他更新删除大同小异

 测试

首先查询一个缓存中没有的数据, 缓存中没有所以去查数据库, 并把结果存到缓存中

再次查询这个code值时, 就会发现直接查询缓存了.

比起以往的先查缓存, 如果没有再查数据库是不是优雅的多了.

当然spring底层实现也是如此, 借用aop的原理, 在执行方法前进行相应的操作

 

参数介绍

cacheNames: 缓存的key的目录名
key: key 名 支持三元表达式
unless: 什么条件下不缓存, 如上图当结果的结果为0时不缓存
condition: 什么时候缓存, 与unless相反
syns:缓存是否使用异步模式
cachemanager:指定缓存管理器

失效时间问题

spring并没有单独为Cacheable指定失效时间的设置, 我们可以对CacheManager进行配置, 达到我们想要的效果.

可以自定义一个cacheManager, 如下图的RedisCacheManager

该构造方法需要3个参数, 分别是

  • cacheWriter : 需要一个缓存写入器
    
  • defaultCacheConfiguration: 默认的失效配置, 理解为默认的配置及失效时间
  • initialCacheConfigurations: 可以自定义缓存配置

我的redis 缓存相关 具体配置文件, 如下, 可直接拷贝使用

 @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        return new RedisCacheManager(
                RedisCacheWriter.lockingRedisCacheWriter(factory),
                this.getRedisCacheConfigurationWithTtl(1),
                this.getRedisCacheConfigurationMap()
        );
    }

    /**
     * 默认失效时间配置
     *
     * @param days 未设置失效事件的key 默认days失效
     */
    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer days) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofDays(days));
    }

    public static final String REGION_LIST_BY_CODE_CACHE_KEY = "region:list";
    public static final String REGION_NAME_BY_CODE_CACHE_KEY = "region:name";

    /**
     * 已知缓存名称的映射以及用于这些缓存的配置
     */
    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        // 自定义缓存名称对应的配置
        redisCacheConfigurationMap.put(REGION_LIST_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(5));
        redisCacheConfigurationMap.put(REGION_NAME_BY_CODE_CACHE_KEY, this.getRedisCacheConfigurationWithTtl(10));
        return redisCacheConfigurationMap;
    }

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐