原理
1、自动配置类:CacheAutoConfiguration
2、缓存的配置类:
3、哪个配置类默认生效:SimpleCacheConfiguration
4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager。
5、可以获取或创建ConcurrentMapCacheManager类型的缓存组件,它的作用是将数据保存在ConcurrentMap中
运行流程(以@Cacheable为例):
1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存,如果没有Cache组件会自动创建。
2、去Cache中查找缓存的内容,使用一个key,默认使用SimpleKeyGenerator生成key。
3、没有查到缓存就调用目标方法。
4、将目标方法返回的结果放进缓存里
总结:@Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行方法并将结果放入缓存,以后再来调用就可以直接使用缓存中的数据。
核心
1、使用CacheManager(默认ConcurrentMapCacheManager)按照名字得到Cache组件(默认ConcurrentMap)。
2、key是使用KeyGenerator(默认SimpleKeyGenerator)生成的。
源码
以【缓存】@Cacheable为例进行分析:
SimpleCacheConfiguration类:
class SimpleCacheConfiguration {
SimpleCacheConfiguration() {
}
@Bean
ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager);
}
}
ConcurrentMapCacheManager类:
@Nullable
public Cache getCache(String name) {
Cache cache = (Cache)this.cacheMap.get(name);
if (cache == null && this.dynamic) {
ConcurrentMap var3 = this.cacheMap;
synchronized(this.cacheMap) {
cache = (Cache)this.cacheMap.get(name);
if (cache == null) {
cache = this.createConcurrentMapCache(name);
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
ConcurrentMapCache类:
private final ConcurrentMap<Object, Object> store;
@Nullable
protected Object lookup(Object key) {
return this.store.get(key);
}
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
return this.fromStoreValue(this.store.computeIfAbsent(key, (k) -> {
try {
return this.toStoreValue(valueLoader.call());
} catch (Throwable var5) {
throw new ValueRetrievalException(key, valueLoader, var5);
}
}));
}
public void put(Object key, @Nullable Object value) {
this.store.put(key, this.toStoreValue(value));
}