当前位置:首页 >焦点 >SpringCache源码分析,你学会了吗? 在使用自定义的码分切点类

SpringCache源码分析,你学会了吗? 在使用自定义的码分切点类

2024-06-28 23:54:11 [百科] 来源:避面尹邢网

SpringCache源码分析,码分你学会了吗?

作者:IT动力 开发 前端 ProxyCachingConfiguration总的析学来说就是声明了一个SpringCacheAnnotationParser和一个CacheInterceptor。在使用自定义的码分切点类,在切点前后切入一个CacheInterceptor来实现缓存的析学逻辑。

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方法,用于返回要导入的配置类列表.

SpringCache源码分析,你学会了吗? 在使用自定义的码分切点类

selectImports会去判断,如果是jdk动态代理,走getProxyImports逻辑。如果是cglib动态代理,走getAspectJImports逻辑。

SpringCache源码分析,你学会了吗? 在使用自定义的码分切点类

我们直接关注JDK动态代理的方法getProxyImports。这里面添加了两个类AutoProxyRegistrar和ProxyCachingConfiguration。

SpringCache源码分析,你学会了吗? 在使用自定义的码分切点类

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获取缓存方法

@Nullableprivate 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获取缓存方法

@Nullableprivate 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获取缓存方法

@Nullableprotected 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方法

@Nullableprotected 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以及实现类

@FunctionalInterfacepublic 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最底层的数据结构就是以一个ConcurrentMapprivate final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);@Override@Nullablepublic 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的源码分析就到此为止了。

责任编辑:武晓燕 来源: 今日头条 Spring源码自定义

(责任编辑:知识)

    推荐文章
    热点阅读