0%

Spring Cache

前言:这几天做公司项目的时候第一次接触CaffineCache,一开始写的是手动操作的版本,近几日做优化利用了Spring集成的接口来进行管理

Spring Cache是什么

官方文档

the Spring Framework provides support for transparently adding caching to an existing Spring application. Similar to the transaction support, the caching abstraction allows consistent use of various caching solutions with minimal impact on the code.

简单来说,Spring定义了一组规范的CRUD API规范,使我们可以方便的操作缓存实体(Redis,Caffine等)

如何配置

application.properties

1
2
3
4
# 定义缓存名称
spring.cache.cache-names=agencyDataIndexOption,realTimeIndex
# 设定延时,最大数据量
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=6s

配置类

配置多个CacheManager:

  • 可以为每个Cache定义不同的CacheManager
  • 可以设定不同的时长
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Configuration
@EnableCaching
@EnableConfigurationProperties(CacheProperties.class)
public class CacheManagerConfiguration {
private final CacheProperties cacheProperties;
public CacheManagerConfiguration(CacheProperties cacheProperties) {
this.cacheProperties = cacheProperties;
}
public interface CacheManagerNames {
String REDIS_CACHE_MANAGER = "redisCacheManager";
String EHCACHE_CACHE_MANAGER = "ehCacheManager";
}

@Bean(name = CacheManagerNames.REDIS_CACHE_MANAGER)
public RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {
Map<String, RedisCacheConfiguration> expires = ImmutableMap.<String, RedisCacheConfiguration>builder()
.put("15", RedisCacheConfiguration.defaultCacheConfig().entryTtl(
Duration.ofMillis(15)
))
.put("30", RedisCacheConfiguration.defaultCacheConfig().entryTtl(
Duration.ofMillis(30)
))
.put("60", RedisCacheConfiguration.defaultCacheConfig().entryTtl(
Duration.ofMillis(60)
))
.put("120", RedisCacheConfiguration.defaultCacheConfig().entryTtl(
Duration.ofMillis(120)
))
.build();

RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(factory)
.withInitialCacheConfigurations(expires)
.build();
return redisCacheManager;
}

@Bean(name = CacheManagerNames.EHCACHE_CACHE_MANAGER)
@Primary
public EhCacheCacheManager ehCacheManager() {
Resource resource = this.cacheProperties.getEhcache().getConfig();
resource = this.cacheProperties.resolveConfigLocation(resource);
EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(
EhCacheManagerUtils.buildCacheManager(resource)
);
ehCacheManager.afterPropertiesSet();
return ehCacheManager;
}
}

使用(CaffineCache为例)

三个注解

  • @Cacheable: Triggers cache population.(当重复使用相同参数调用方法的时候,方法本身不会被调用执行,即方法本身被略过了,取而代之的是方法的结果直接从缓存中找到并返回了)
  • @CacheEvict: Triggers cache eviction.
  • @CachePut: Updates the cache without interfering with the method execution.(这个注释可以确保方法被执行,同时方法的返回值也被记录到缓存中。)

    代码实例

    在Service中使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Cacheable(cacheNames = "businessIndex", sync = true)
    @Override
    public BseBusinessIndexPO getCachedIndex(Integer id) {
    return getIndexById(id);
    }

    @Cacheable(cacheNames = "businessIndex", sync = true)
    @Override
    public BseBusinessIndexPO getCachedIndex(String tableName, String fieldName) {
    return businessIndexMapper.selectByTableAndField(tableName, fieldName);
    }

手动管理缓存,利用Spring默认的CacheManager

1
2
3
4
5
6
7
8
9
10
11
12
13
@GetMapping("/{cacheName}/{cacheKey}/evict")
public WebApiResponse<String> evict(@PathVariable("cacheName") String cacheName,
@PathVariable("cacheKey") String cacheKey) {
try {
Object key=generateKey(cacheKey);
Optional.ofNullable(cacheManager.getCache(cacheName))
.ifPresent(k -> k.evict(key));
return WebApiResponse.success(
String.format("缓存cacheName: %s at %s清除成功", cacheName, (String) cacheKey));
} catch (Exception e) {
return WebApiResponse.error(e.getMessage());
}
}

reference:
https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/integration.html#cache
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html