1、入口说明
@EnableCaching是开启SpringCache的一个总开关,开启时候我们的缓存相关注解才会生效,所以我们@EnableCaching开始作为入口进行分析,
2、分析@EnableCaching注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class) // 这里有一个Import,导入了一个Selector类
public @interface EnableCaching {
// 是否创建cglib代理,默认为false, 也就是使用jdk动态代理
boolean proxyTargetClass() default false;
// 增强模式 默认使用JDK动态代理,引入cglib可以使用ASPECTJ
AdviceMode mode() default AdviceMode.PROXY;
// 排序字段
int order() default Ordered.LOWEST_PRECEDENCE;
}
2.1、分析导入的CachingConfigurationSelector类
public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {
// ...此处省略一万行代码
// CachingConfigurationSelector继承了AdviceModeImportSelector, 而AdviceModeImportSelector又实现了ImportSelector
// 所以我们实现类selectImports,用于返回要导入的配置类列表
@Override
public String[] selectImports(AdviceMode adviceMode) {
// 如果是jdk动态代理,走getProxyImports逻辑。如果是cglib动态代理,走getAspectJImports逻辑
switch (adviceMode) {
case PROXY:
return getProxyImports();
case ASPECTJ:
return getAspectJImports();
default:
return null;
}
}
// 获取要进行自动配置的配置类
private String[] getProxyImports() {
List<String> result = new ArrayList<>(3);
// 这里添加了两个类,AutoProxyRegistrar(自动代理注册器),ProxyCachingConfiguration(代理缓存配置类)
// AutoProxyRegistrar点进去可以发现,里面其实就是提供了registerBeanDefinitions方法用于注册BeanDefinition
result.add(AutoProxyRegistrar.class.getName());
// ProxyCachingConfiguration点进去发现,配置类缓存相关的一些Bean(就是SpringCache的一些核心Bean)
result.add(ProxyCachingConfiguration.class.getName());
if (jsr107Present && jcacheImplPresent) {
result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
}
return StringUtils.toStringArray(result);
}
// ...此处省略一万行代码
}
CachingConfigurationSelector继承了AdviceModeImportSelector, 而AdviceModeImportSelector又实现了ImportSelector,所以我们实现了selectImports方法,用于返回要导入的配置类列表.
selectImports会去判断,如果是jdk动态代理,走getProxyImports逻辑。如果是cglib动态代理,走getAspectJImports逻辑。
我们直接关注JDK动态代理的方法getProxyImports。这里面添加了两个类AutoProxyRegistrar和ProxyCachingConfiguration。
AutoProxyRegistrar点进去可以发现,里面其实就是提供了registerBeanDefinitions方法用于注册BeanDefinition。
ProxyCachingConfiguration点进去发现,配置类缓存相关的一些Bean(就是SpringCache的一些核心Bean),所以我们会重点关注ProxyCachingConfiguration并着重分析。
2.1.1、分析ProxyCachingConfiguration配置类
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
// BeanFactoryCacheOperationSourceAdvisor是对CacheOperationSource进行增强,其实就是添加一个拦截器,用于获取相关缓存的注解信息
// 所以有些逻辑会在CacheInterceptor里
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(
CacheOperationSource cacheOperationSource, CacheInterceptor cacheInterceptor) {
BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();
advisor.setCacheOperationSource(cacheOperationSource);
advisor.setAdvice(cacheInterceptor);
if (this.enableCaching != null) {
advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));
}
return advisor;
}
// 定义一个CacheOperationSource,主要用于获取类或者方法上的注解。
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {
return new AnnotationCacheOperationSource();
}
// 定义了一个拦截器,该拦截器用于用于拦截缓存相关注解,做AOP操作。比如先查询缓存,查询到直接返回,查询不到就执行方法体,将结果写入缓存。
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {
CacheInterceptor interceptor = new CacheInterceptor();
// 缓存拦截器在这里注入了cacheManager(缓存管理器)
interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);
interceptor.setCacheOperationSource(cacheOperationSource);
return interceptor;
}
}
来分析一下BeanFactoryCacheOperationSourceAdvisor
public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private CacheOperationSource cacheOperationSource;
// 定义我们自己的切点,缓存操作切点
private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
// 该切点存在一个方法,获取CacheOperationSource(获取切点的那些注解操作)。
@Override
@Nullable
protected CacheOperationSource getCacheOperationSource() {
return cacheOperationSource;
}
};
// 使用该方法设置CacheOperationSource,在上一层有设置advisor.setCacheOperationSource(cacheOperationSource);
// 把这个数据塞入BeanFactoryCacheOperationSourceAdvisor, 以便于在自定义的切点类CacheOperationSourcePointcut中可以获取
public void setCacheOperationSource(CacheOperationSource cacheOperationSource) {
this.cacheOperationSource = cacheOperationSource;
}
// 设置ClassFilter到CacheOperationSourcePointcut
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
// 重写getPointcut。也就是获取切点的方法,因为需要对切点进行增强
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
BeanFactoryCacheOperationSourceAdvisor继承了AbstractBeanFactoryPointcutAdvisor,重写了Pointcut getPointcut()方法。
使用自定义的切点类CacheOperationSourcePointcut来作为切面的切点。而里面需要用到CacheOperationSource和ClassFilter。在BeanFactoryCacheOperationSourceAdvisor实例化时就已经设置。
而上面又执行了advisor.setAdvice(cacheInterceptor); 其实就是对这个切点添加了一个缓存拦截器,所以核心逻辑就在拦截器里面。
先再来看一下AnnotationCacheOperationSource
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {
private final boolean publicMethodsOnly;
// 缓存注解解析集合
private final Set<CacheAnnotationParser> annotationParsers;
public AnnotationCacheOperationSource() {
this(true);
}
public AnnotationCacheOperationSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
// 重点:解析集合从SpringCacheAnnotationParser中获取,这个解析类就是解析注解的核心
this.annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
}
// ...此处省略一万行代码
// 判断是否时候选类
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (CacheAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
// 重点:查找类级别的CacheOperation列表,就是看标注在类上的@Cacheable,@CacheEvict的集合
@Override
@Nullable
protected Collection<CacheOperation> findCacheOperations(Class<?> clazz) {
return determineCacheOperations(parser -> parser.parseCacheAnnotations(clazz));
}
// 重点:查找方法级别的CacheOperation列表,就是看标注在方法上的@Cacheable,@CacheEvict的集合
@Override
@Nullable
protected Collection<CacheOperation> findCacheOperations(Method method) {
return determineCacheOperations(parser -> parser.parseCacheAnnotations(method));
}
// ...此处省略一万行代码
}
接着看一下SpringCacheAnnotationParser
public class SpringCacheAnnotationParser implements CacheAnnotationParser, Serializable {
private static final Set<Class<? extends Annotation>> CACHE_OPERATION_ANNOTATIONS = new LinkedHashSet<>(8);
// 初始化缓存操作的注解集合
static {
CACHE_OPERATION_ANNOTATIONS.add(Cacheable.class);
CACHE_OPERATION_ANNOTATIONS.add(CacheEvict.class);
CACHE_OPERATION_ANNOTATIONS.add(CachePut.class);
CACHE_OPERATION_ANNOTATIONS.add(Caching.class);
}
// 解析类级别的注解,封装为CacheOperation集合
@Override
@Nullable
public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) {
DefaultCacheConfig defaultConfig = new DefaultCacheConfig(type);
return parseCacheAnnotations(defaultConfig, type);
}
// 解析方法级别的注解,封装为CacheOperation集合
@Override
@Nullable
public Collection<CacheOperation> parseCacheAnnotations(Method method) {
DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass());
return parseCacheAnnotations(defaultConfig, method);
}
// 解析注解
@Nullable
private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false);
if (ops != null && ops.size() > 1) {
// More than one operation found -> local declarations override interface-declared ones...
Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);
if (localOps != null) {
return localOps;
}
}
return ops;
}
// 具体解析注解的方法,包含了Cacheable,CacheEvict,CachePut,Caching等
@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;
}
// ...此处省略了一万行代码,基本这个类都是解析这些注解并封装为CacheOperation集合
}
所以,SpringCacheAnnotationParser的作用就是将这些注解解析出来,并且封装为Collection<CacheOperation>,供其他地方使用。
ProxyCachingConfiguration总的来说就是声明了一个SpringCacheAnnotationParser和一个CacheInterceptor。在使用自定义的切点类,在切点前后切入一个CacheInterceptor来实现缓存的逻辑。
所以我们就找到的缓存的核心类CacheInterceptor,并且在构造拦截器时,传入了cacheManager作为缓存管理。
2.1.2、分析CacheInterceptor类
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);
}
};
Object target = invocation.getThis();
Assert.state(target != null, "Target must not be null");
try {
// 调用父类的execute方法,实现缓存的逻辑
return execute(aopAllianceInvoker, target, method, invocation.getArguments());
}
catch (CacheOperationInvoker.ThrowableWrapper th) {
throw th.getOriginal();
}
}
}
可以看到,这个类很简单,就是拿到原方法的invoke,然后通过父类CacheAspectSupport的execute方法实现缓存逻辑。
关注CacheAspectSupport的execute方法
public abstract class CacheAspectSupport extends AbstractCacheInvoker
implements BeanFactoryAware, InitializingBean, SmartInitializingSingleton {
protected final Log logger = LogFactory.getLog(getClass());
private final Map<CacheOperationCacheKey, CacheOperationMetadata> metadataCache = new ConcurrentHashMap<>(1024);
private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator();
@Nullable
private CacheOperationSource cacheOperationSource;
private SingletonSupplier<KeyGenerator> keyGenerator = SingletonSupplier.of(SimpleKeyGenerator::new);
@Nullable
private SingletonSupplier<CacheResolver> cacheResolver;
@Nullable
private BeanFactory beanFactory;
private boolean initialized = false;
@Nullable
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// 如果bean已经被初始化了,则调用相应的缓存增强
if (this.initialized) {
Class<?> targetClass = getTargetClass(target);
CacheOperationSource cacheOperationSource = getCacheOperationSource();
if (cacheOperationSource != null) {
// 通过CacheOperationSource,获取所有的CacheOperation列表(就是那一堆标有缓存注解的类和方法的集合)
Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) {
// 调用重载的execute方法
return execute(invoker, method,
new CacheOperationContexts(operations, method, args, target, targetClass));
}
}
}
// 否则,执行原方法返回即可
return invoker.invoke();
}
// 执行方法(核心)
@Nullable
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
// Special handling of synchronized invocation
if (contexts.isSynchronized()) {
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
Cache cache = context.getCaches().iterator().next();
try {
return wrapCacheValue(method, handleSynchronizedGet(invoker, key, cache));
} catch (Cache.ValueRetrievalException ex) {
// Directly propagate ThrowableWrapper from the invoker,
// or potentially also an IllegalArgumentException etc.
ReflectionUtils.rethrowRuntimeException(ex.getCause());
}
} else {
// No caching required, only call the underlying method
return invokeOperation(invoker);
}
}
// 如果存在@CacheEvict注解、并且标记为在调用前执行,调用processCacheEvicts进行缓存清除操作
processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
CacheOperationExpressionEvaluator.NO_RESULT);
// 如果存在Cacheable注解、调用findCachedItem查询缓存
Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));
// 如果没有命中缓存,则调用cachePutRequests,存储在List<CachePutRequest>中,后续执行原始方法后会写入缓存
List<CachePutRequest> cachePutRequests = new ArrayList<>();
if (cacheHit == null) {
collectPutRequests(contexts.get(CacheableOperation.class),
CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
}
Object cacheValue;
Object returnValue;
// 如果缓存命中且没有@CachePut注解,使用缓存的值作为返回值
if (cacheHit != null && !hasCachePut(contexts)) {
// If there are no put requests, just use the cache hit
cacheValue = cacheHit.get();
returnValue = wrapCacheValue(method, cacheValue);
}
// 缓存没有命中或者有@CachePut注解
else {
// 调用原始方法作为返回值
returnValue = invokeOperation(invoker);
// 将原始方法的返回值作为缓存值
cacheValue = unwrapReturnValue(returnValue);
}
// 如果有@CachePut注解,则新增到cachePutRequests
collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
// 缓存未命中或者存在@CachePut注解,调用CachePutRequest的apply方法将数据写入缓存
for (CachePutRequest cachePutRequest : cachePutRequests) {
cachePutRequest.apply(cacheValue);
}
// 如果有@CacheEvict注解,并且标记为在调用后执行,则还需要执行清除缓存操作
processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
return returnValue;
}
// 此处省略一万行代码
}
总结来说,
- 如果存在@CacheEvict注解,并且标记在方法执行前执行,就执行清除缓存相关操作。
- 使用findCachedItem获取缓存,缓存没有命中,加入collectPutRequests,后续进行写入缓存操作。
- 如果命中缓存并且没有@CachePut注解,获取命中的值作为方法的返回值
- 如果没有命中,或者包含了@CachePut注解,加入collectPutRequests,后续进行写入缓存操作。
- 遍历cachePutRequests,将需要写入缓存的数据写入缓存
- 如果存在@CacheEvict注解,并且标记在方法执行后执行,就执行清除缓存相关操作。
还没完呢,因为我们定义的CacheManager怎么没有用到呢?我们继续跟踪下去,以get缓存方法为例子分析。
关注findCachedItem获取缓存方法
@Nullable
private Cache.ValueWrapper findCachedItem(Collection<CacheOperationContext> contexts) {
// 遍历上下文列表
Object result = CacheOperationExpressionEvaluator.NO_RESULT;
for (CacheOperationContext context : contexts) {
if (isConditionPassing(context, result)) {
Object key = generateKey(context, result);
// 根据生成的key获取缓存值
Cache.ValueWrapper cached = findInCaches(context, key);
if (cached != null) {
return cached;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());
}
}
}
}
return null;
}
关注findInCaches获取缓存方法
@Nullable
private Cache.ValueWrapper findInCaches(CacheOperationContext context, Object key) {
// 遍历缓存集合(getCaches),使用缓存的key去和获取缓存
for (Cache cache : context.getCaches()) {
// 最终是使用Cache接口的get方法去获取缓存的
Cache.ValueWrapper wrapper = doGet(cache, key);
if (wrapper != null) {
if (logger.isTraceEnabled()) {
logger.trace("Cache entry for key '" + key + "' found in cache '" + cache.getName() + "'");
}
return wrapper;
}
}
return null;
}
关注doGet获取缓存方法
@Nullable
protected Cache.ValueWrapper doGet(Cache cache, Object key) {
try {
return cache.get(key);
}
catch (RuntimeException ex) {
getErrorHandler().handleCacheGetError(ex, cache, key);
return null; // If the exception is handled, return a cache miss
}
}
我们发现,最终是通过Cache接口的get方法去获取缓存的,那么我们只要知道Cache集合对象是在哪里传入进来的就清楚了整个逻辑。
重新回到execute方法
@Nullable
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// Check whether aspect is enabled (to cope with cases where the AJ is pulled in automatically)
if (this.initialized) {
Class<?> targetClass = getTargetClass(target);
CacheOperationSource cacheOperationSource = getCacheOperationSource();
if (cacheOperationSource != null) {
Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) {
// 这里创建了一个CacheOperationContexts,我们有理由猜测CacheOperationContext.getCaches方法就是在这里面
return execute(invoker, method,
new CacheOperationContexts(operations, method, args, target, targetClass));
}
}
}
return invoker.invoke();
}
跟踪CacheOperationContexts
private class CacheOperationContexts {
// 就是一个CacheOperationContext的集合,key是CacheOperation或者其子类
private final MultiValueMap<Class<? extends CacheOperation>, CacheOperationContext> contexts;
// 是否开启了sync=true属性
private final boolean sync;
public CacheOperationContexts(Collection<? extends CacheOperation> operations, Method method,
Object[] args, Object target, Class<?> targetClass) {
// 根据CacheOperation集合,方法,参数创建了一个CacheOperationContext集合
this.contexts = new LinkedMultiValueMap<>(operations.size());
for (CacheOperation op : operations) {
// 重点:getOperationContext是具体创建CacheOperationContext的方法
this.contexts.add(op.getClass(), getOperationContext(op, method, args, target, targetClass));
}
// 获取sync属性并赋值给this.sync
this.sync = determineSyncFlag(method);
}
public Collection<CacheOperationContext> get(Class<? extends CacheOperation> operationClass) {
Collection<CacheOperationContext> result = this.contexts.get(operationClass);
return (result != null ? result : Collections.emptyList());
}
public boolean isSynchronized() {
return this.sync;
}
// ...此处省略了一万行代码
}
关注getOperationContext创建CacheOperationContext
protected CacheOperationContext getOperationContext(
CacheOperation operation, Method method, Object[] args, Object target, Class<?> targetClass) {
CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass);
// 其实就是实例化一个CacheOperationContext
return new CacheOperationContext(metadata, args, target);
}
其实就是拿到CacheOperationMetadata(CacheOperation的元数据信息),然后传给CacheOperationContext进行实例化CacheOperationContext。
关注CacheOperationContext的构造方法
上面实例化了CacheOperationContext,所以其构造方法内一定做了写什么事情。比如初始化操作。
// 缓存的集合
private final Collection<? extends Cache> caches;
public CacheOperationContext(CacheOperationMetadata metadata, Object[] args, Object target) {
this.metadata = metadata;
this.args = extractArgs(metadata.method, args);
this.target = target;
// 初始化了缓存名称列表和缓存集合
this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver);
this.cacheNames = createCacheNames(this.caches);
}
关注getCaches(获取缓存集合)
protected Collection<? extends Cache> getCaches(
CacheOperationInvocationContext<CacheOperation> context, CacheResolver cacheResolver) {
// 这里可以知道是通过CacheResolver来获取的缓存集合
Collection<? extends Cache> caches = cacheResolver.resolveCaches(context);
if (caches.isEmpty()) {
throw new IllegalStateException("No cache could be resolved for '" +
context.getOperation() + "' using resolver '" + cacheResolver +
"'. At least one cache should be provided per cache operation.");
}
return caches;
}
关注CacheResolver以及实现类
@FunctionalInterface
public interface CacheResolver {
// 根据CacheOperationInvocationContext获取缓存集合
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
}
CacheResolver的抽象实现类AbstractCacheResolver
public abstract class AbstractCacheResolver implements CacheResolver, InitializingBean {
// 这里就有CacheManager(缓存管理器)
@Nullable
private CacheManager cacheManager;
protected AbstractCacheResolver() {
}
// 构造注入
protected AbstractCacheResolver(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
// set注入
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
// 获取CacheManager
public CacheManager getCacheManager() {
Assert.state(this.cacheManager != null, "No CacheManager set");
return this.cacheManager;
}
@Override
public void afterPropertiesSet() {
Assert.notNull(this.cacheManager, "CacheManager is required");
}
// 获取缓存集合
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
// 先获取缓存名称
Collection<String> cacheNames = getCacheNames(context);
if (cacheNames == null) {
return Collections.emptyList();
}
Collection<Cache> result = new ArrayList<>(cacheNames.size());
// 遍历名称,通过CacheManager获取缓存,加入缓存集合
for (String cacheName : cacheNames) {
Cache cache = getCacheManager().getCache(cacheName);
if (cache == null) {
throw new IllegalArgumentException("Cannot find cache named '" +
cacheName + "' for " + context.getOperation());
}
result.add(cache);
}
return result;
}
// 获取缓存名称集合
@Nullable
protected abstract Collection<String> getCacheNames(CacheOperationInvocationContext<?> context);
}
而我们的CacheManager默认使用SimpleCacheManager,我们注入了CustomRedisCacheManager, 所以会调用CustomRedisCacheManager的getCache方法获取缓存。
而getCache方法在父类AbstractCacheManager已经实现了。
// SpringCache最底层的数据结构就是以一个ConcurrentMap
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
@Override
@Nullable
public Cache getCache(String name) {
// 先从cacheMap中获取Cache, 获取到了直接返回
Cache cache = this.cacheMap.get(name);
if (cache != null) {
return cache;
}
// 获取不到,使用双重检测所写入数据到cacheMap
Cache missingCache = getMissingCache(name);
if (missingCache != null) {
// Fully synchronize now for missing cache registration
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
cache = decorateCache(missingCache);
this.cacheMap.put(name, cache);
updateCacheNames(name);
}
}
}
return cache;
}
到了这里,SpringCache的流程我们就真正的清楚了。
所以,SpringCache的源码分析就到此为止了。