【Cache核心】Spring缓存实现原理

一、自动配置类: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

发布了147 篇原创文章 · 获赞 88 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/zpwangshisuifeng/article/details/101110942