spring cache

在 spring-context模块下定义的接口:

spring cache 抽象接口

org.springframework.cache.Cache

org.springframework.cache.CacheManager

用于生产缓存的key

org.springframework.cache.interceptor.KeyGenerator

org.springframework.cache.interceptor.CacheResolver

在 spring boot autoconfigure 模块下 cache 包 完成了 对 cache 组件的 自动配置

该枚举类定义了 cache 的类型

org.springframework.boot.autoconfigure.cache.CacheType

java 复制代码
/**
 * Supported cache types (defined in order of precedence).
 *
 * @author Stephane Nicoll
 * @author Phillip Webb
 * @author Eddú Meléndez
 * @since 1.3.0
 */
public enum CacheType {

	/**
	 * Generic caching using 'Cache' beans from the context.
	 */
	GENERIC,

	/**
	 * JCache (JSR-107) backed caching.
	 */
	JCACHE,

	/**
	 * EhCache backed caching.
	 */
	EHCACHE,

	/**
	 * Hazelcast backed caching.
	 */
	HAZELCAST,

	/**
	 * Infinispan backed caching.
	 */
	INFINISPAN,

	/**
	 * Couchbase backed caching.
	 */
	COUCHBASE,

	/**
	 * Redis backed caching.
	 */
	REDIS,

	/**
	 * Caffeine backed caching.
	 */
	CAFFEINE,

	/**
	 * Simple in-memory caching.
	 */
	SIMPLE,

	/**
	 * No caching.
	 */
	NONE

}

缓存类型的枚举顺序,就是使用的优先级。

一般常用的缓存如 redis,ehcahce,caffeine 的优先级为:

ehcahce redis caffeine

根据 spring boot autoconfigure 模块下的 spring.factories 文件

XML 复制代码
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration 完成了 缓存的 自动配置

代码解析:

java 复制代码
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;
		}

	}

这段代码是将 缓存类信息注册到spring中 以便后续进行实例化。

ehcache:

java 复制代码
static class ConfigAvailableCondition extends ResourceCondition {

		ConfigAvailableCondition() {
			super("EhCache", "spring.cache.ehcache.config", "classpath:/ehcache.xml");
		}

	}

判断 需要存在 ehcache.xml才进行ehcahce自动配置。

java 复制代码
@Bean
	@ConditionalOnMissingBean
	CacheManager ehCacheCacheManager(CacheProperties cacheProperties) {
		Resource location = cacheProperties.resolveConfigLocation(cacheProperties.getEhcache().getConfig());
		if (location != null) {
			return EhCacheManagerUtils.buildCacheManager(location);
		}
		return EhCacheManagerUtils.buildCacheManager();
	}
java 复制代码
@Bean
	EhCacheCacheManager cacheManager(CacheManagerCustomizers customizers, CacheManager ehCacheCacheManager) {
		return customizers.customize(new EhCacheCacheManager(ehCacheCacheManager));
	}
java 复制代码
// net.sf.ehcache.CacheManager#addConfiguredCaches
// 将 ehcache.xml 读取到的 缓存信息写入 cacheManager 中的 net.sf.ehcache.CacheManager#ehcaches 中
private void addConfiguredCaches(ConfigurationHelper configurationHelper) {
        Set unitialisedCaches = configurationHelper.createCaches();
        for (Iterator iterator = unitialisedCaches.iterator(); iterator.hasNext();) {
            Ehcache unitialisedCache = (Ehcache) iterator.next();
            addCacheNoCheck(unitialisedCache, true);

            // add the cache decorators for the cache, if any
            List<Ehcache> cacheDecorators = configurationHelper.createCacheDecorators(unitialisedCache);
            for (Ehcache decoratedCache : cacheDecorators) {
                addOrReplaceDecoratedCache(unitialisedCache, decoratedCache);
            }
        }
    }

最终会将缓存信息写到 org.springframework.cache.support.AbstractCacheManager#cacheMap

在使用时,需要加入 org.springframework.cache.annotation.EnableCaching 注解

会注入一个切面,完成对缓存相关的注解的处理

java 复制代码
@Nullable
	private Collection<CacheOperation> parseCacheAnnotations(
			DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) {

		Collection<? extends Annotation> anns = (localOnly ?
				AnnotatedElementUtils.getAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS) :
				AnnotatedElementUtils.findAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS));
		if (anns.isEmpty()) {
			return null;
		}

		final Collection<CacheOperation> ops = new ArrayList<>(1);
		anns.stream().filter(ann -> ann instanceof Cacheable).forEach(
				ann -> ops.add(parseCacheableAnnotation(ae, cachingConfig, (Cacheable) ann)));
		anns.stream().filter(ann -> ann instanceof CacheEvict).forEach(
				ann -> ops.add(parseEvictAnnotation(ae, cachingConfig, (CacheEvict) ann)));
		anns.stream().filter(ann -> ann instanceof CachePut).forEach(
				ann -> ops.add(parsePutAnnotation(ae, cachingConfig, (CachePut) ann)));
		anns.stream().filter(ann -> ann instanceof Caching).forEach(
				ann -> parseCachingAnnotation(ae, cachingConfig, (Caching) ann, ops));
		return ops;
	}

在对应方法上添加 @Cacheable 注解,就可以使用 spring cache了。

java 复制代码
@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public CacheInterceptor cacheInterceptor() {
		CacheInterceptor interceptor = new CacheInterceptor();
		interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
		interceptor.setCacheOperationSource(cacheOperationSource());
		return interceptor;
	}
java 复制代码
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {

	@Override
	@Nullable
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();

		CacheOperationInvoker aopAllianceInvoker = () -> {
			try {
				return invocation.proceed();
			}
			catch (Throwable ex) {
				throw new CacheOperationInvoker.ThrowableWrapper(ex);
			}
		};

		try {
			return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
		}
		catch (CacheOperationInvoker.ThrowableWrapper th) {
			throw th.getOriginal();
		}
	}

}

完成方法的拦截

相关推荐
ka2x1 小时前
订单折扣金额分摊算法|代金券分摊|收银系统|积分分摊|分摊|精度问题|按比例分配|钱分摊|钱分配
java·c语言·c++·python·算法·spring·spring cloud
职略3 小时前
负载均衡类型和算法解析
java·运维·分布式·算法·负载均衡
A22743 小时前
LeetCode 196, 73, 105
java·算法·leetcode
容若只如初见4 小时前
项目实战--Spring Boot + Minio文件切片上传下载
java·spring boot·后端
阿里巴巴P8资深技术专家4 小时前
Java常用算法&集合扩容机制分析
java·数据结构·算法
weixin_440401694 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
码农爱java4 小时前
Spring Boot 中的监视器是什么?有什么作用?
java·spring boot·后端·面试·monitor·监视器
zengson_g4 小时前
当需要对大量数据进行排序操作时,怎样优化内存使用和性能?
java·数据库·算法·排序算法
血战灬狂龙5 小时前
pom.xml文件加载后没有变成maven图标
xml·java·maven
Apifox.5 小时前
什么是 HTTP POST 请求?初学者指南与示范
后端·http·学习方法·web