一、自动配置类:CacheAutoConfiguration
二、添加缓存配置类
SimpleCacheConfiguration【默认生效】
/**
* {@link ImportSelector} to add {@link CacheType} configuration classes.
* org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
* org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
* org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
* org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
* org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
* org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
* org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
* org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
* org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
* org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】
* org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
*/
static class CacheConfigurationImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
CacheType[] types = CacheType.values();
String[] imports = new String[types.length];
for (int i = 0; i < types.length; i++) {
imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
}
return imports;
}
}
三、默认匹配 SimpleCacheConfiguration
四、注册缓存管理器 【ConcurrentMapCacheManager】
1、数据被缓存在 cacheMap,key为缓存的名字,value为Cache对象。
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
2、getCache()方法,根据缓存名,获取缓存对象Cache。如果获取的Cache的对象为null,会调用createConcurrentMapCache()方法创建一个Cache.
@Override
@Nullable
public Cache getCache(String name) {
Cache cache = this.cacheMap.get(name);
if (cache == null && this.dynamic) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
cache = createConcurrentMapCache(name);
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
3、createConcurrentMapCache方法为创建一个Cache对【ConcurrentMapCache】象。
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),
isAllowNullValues(), actualSerialization);
}
4、ConcurrentMapCache是一个缓存组件。其中store是一个Map,其作用是缓存数据,key为缓存名,value为数据。looup方法为获取数据。put方法为报错数据。
private final ConcurrentMap<Object, Object> store;
@Override
@Nullable
protected Object lookup(Object key) {
return this.store.get(key);
}
@Override
public void put(Object key, @Nullable Object value) {
this.store.put(key, toStoreValue(value));
}
五、运行流程
对于注解:@Cacheable:
1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存如果没有,Cache组件会自动创建。
2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数。key是按照某种策略生成的, 默认是使用SimpleKeyGenerator生成key。
3、没有查到缓存就调用目标方法。
4、将目标方法返回的结果放进缓存。
/**
* Compute the key for the given caching operation.
*/
@Nullable
protected Object generateKey(@Nullable Object result) {
if (StringUtils.hasText(this.metadata.operation.getKey())) {
EvaluationContext evaluationContext = createEvaluationContext(result);
return evaluator.key(this.metadata.operation.getKey(), this.metadata.methodKey, evaluationContext);
}
return this.metadata.keyGenerator.generate(this.target, this.metadata.method, this.args);
}
public class SimpleKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return generateKey(params);
}
/**
如果没有参数;key=new SimpleKey();
* 如果有一个参数:key=参数的值
* 如果有多个参数:key=new SimpleKey(params);
*/
public static Object generateKey(Object... params) {
if (params.length == 0) {
return SimpleKey.EMPTY;
}
if (params.length == 1) {
Object param = params[0];
if (param != null && !param.getClass().isArray()) {
return param;
}
}
return new SimpleKey(params);
}
}
public class SimpleKey implements Serializable {
/** An empty key. */
public static final SimpleKey EMPTY = new SimpleKey();
private final Object[] params;
private final int hashCode;
/**
* Create a new {@link SimpleKey} instance.
* @param elements the elements of the key
*/
public SimpleKey(Object... elements) {
Assert.notNull(elements, "Elements must not be null");
this.params = new Object[elements.length];
System.arraycopy(elements, 0, this.params, 0, elements.length);
this.hashCode = Arrays.deepHashCode(this.params);
}
@Override
public boolean equals(Object other) {
return (this == other ||
(other instanceof SimpleKey && Arrays.deepEquals(this.params, ((SimpleKey) other).params)));
}
@Override
public final int hashCode() {
return this.hashCode;
}
@Override
public String toString() {
return getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";
}
}
六、总结
(1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件
(2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator