在 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();
}
}
}
完成方法的拦截