SpringCache源碼分析,你學(xué)會(huì)了嗎?
1、入口說明
@EnableCaching是開啟SpringCache的一個(gè)總開關(guān),開啟時(shí)候我們的緩存相關(guān)注解才會(huì)生效,所以我們@EnableCaching開始作為入口進(jìn)行分析,
2、分析@EnableCaching注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class) // 這里有一個(gè)Import,導(dǎo)入了一個(gè)Selector類
public @interface EnableCaching {
    // 是否創(chuàng)建cglib代理,默認(rèn)為false, 也就是使用jdk動(dòng)態(tài)代理
    boolean proxyTargetClass() default false;
    // 增強(qiáng)模式 默認(rèn)使用JDK動(dòng)態(tài)代理,引入cglib可以使用ASPECTJ
    AdviceMode mode() default AdviceMode.PROXY;
    // 排序字段
    int order() default Ordered.LOWEST_PRECEDENCE;
}2.1、分析導(dǎo)入的CachingConfigurationSelector類
public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {
    // ...此處省略一萬行代碼
    // CachingConfigurationSelector繼承了AdviceModeImportSelector, 而AdviceModeImportSelector又實(shí)現(xiàn)了ImportSelector
    // 所以我們實(shí)現(xiàn)類selectImports,用于返回要導(dǎo)入的配置類列表
    @Override
    public String[] selectImports(AdviceMode adviceMode) {
        // 如果是jdk動(dòng)態(tài)代理,走getProxyImports邏輯。如果是cglib動(dòng)態(tài)代理,走getAspectJImports邏輯
        switch (adviceMode) {
            case PROXY:
                return getProxyImports();
            case ASPECTJ:
                return getAspectJImports();
            default:
                return null;
        }
    }
    // 獲取要進(jìn)行自動(dòng)配置的配置類
    private String[] getProxyImports() {
        List<String> result = new ArrayList<>(3);
        // 這里添加了兩個(gè)類,AutoProxyRegistrar(自動(dòng)代理注冊(cè)器),ProxyCachingConfiguration(代理緩存配置類)
        // AutoProxyRegistrar點(diǎn)進(jìn)去可以發(fā)現(xiàn),里面其實(shí)就是提供了registerBeanDefinitions方法用于注冊(cè)BeanDefinition
        result.add(AutoProxyRegistrar.class.getName());
        // ProxyCachingConfiguration點(diǎn)進(jìn)去發(fā)現(xiàn),配置類緩存相關(guān)的一些Bean(就是SpringCache的一些核心Bean)
        result.add(ProxyCachingConfiguration.class.getName());
        if (jsr107Present && jcacheImplPresent) {
            result.add(PROXY_JCACHE_CONFIGURATION_CLASS);
        }
        return StringUtils.toStringArray(result);
    }
    // ...此處省略一萬行代碼
}CachingConfigurationSelector繼承了AdviceModeImportSelector, 而AdviceModeImportSelector又實(shí)現(xiàn)了ImportSelector,所以我們實(shí)現(xiàn)了selectImports方法,用于返回要導(dǎo)入的配置類列表.
selectImports會(huì)去判斷,如果是jdk動(dòng)態(tài)代理,走getProxyImports邏輯。如果是cglib動(dòng)態(tài)代理,走getAspectJImports邏輯。
我們直接關(guān)注JDK動(dòng)態(tài)代理的方法getProxyImports。這里面添加了兩個(gè)類AutoProxyRegistrar和ProxyCachingConfiguration。
AutoProxyRegistrar點(diǎn)進(jìn)去可以發(fā)現(xiàn),里面其實(shí)就是提供了registerBeanDefinitions方法用于注冊(cè)BeanDefinition。
ProxyCachingConfiguration點(diǎn)進(jìn)去發(fā)現(xiàn),配置類緩存相關(guān)的一些Bean(就是SpringCache的一些核心Bean),所以我們會(huì)重點(diǎn)關(guān)注ProxyCachingConfiguration并著重分析。
2.1.1、分析ProxyCachingConfiguration配置類
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
    // BeanFactoryCacheOperationSourceAdvisor是對(duì)CacheOperationSource進(jìn)行增強(qiáng),其實(shí)就是添加一個(gè)攔截器,用于獲取相關(guān)緩存的注解信息
    // 所以有些邏輯會(huì)在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;
    }
    // 定義一個(gè)CacheOperationSource,主要用于獲取類或者方法上的注解。
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public CacheOperationSource cacheOperationSource() {
        return new AnnotationCacheOperationSource();
    }
    // 定義了一個(gè)攔截器,該攔截器用于用于攔截緩存相關(guān)注解,做AOP操作。比如先查詢緩存,查詢到直接返回,查詢不到就執(zhí)行方法體,將結(jié)果寫入緩存。
    @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;
    // 定義我們自己的切點(diǎn),緩存操作切點(diǎn)
    private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() {
        // 該切點(diǎn)存在一個(gè)方法,獲取CacheOperationSource(獲取切點(diǎn)的那些注解操作)。
        @Override
        @Nullable
        protected CacheOperationSource getCacheOperationSource() {
            return cacheOperationSource;
        }
    };
    
    // 使用該方法設(shè)置CacheOperationSource,在上一層有設(shè)置advisor.setCacheOperationSource(cacheOperationSource);
    // 把這個(gè)數(shù)據(jù)塞入BeanFactoryCacheOperationSourceAdvisor, 以便于在自定義的切點(diǎn)類CacheOperationSourcePointcut中可以獲取
    public void setCacheOperationSource(CacheOperationSource cacheOperationSource) {
        this.cacheOperationSource = cacheOperationSource;
    }
    
    // 設(shè)置ClassFilter到CacheOperationSourcePointcut
    public void setClassFilter(ClassFilter classFilter) {
        this.pointcut.setClassFilter(classFilter);
    }
    // 重寫getPointcut。也就是獲取切點(diǎn)的方法,因?yàn)樾枰獙?duì)切點(diǎn)進(jìn)行增強(qiáng)
    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }
}BeanFactoryCacheOperationSourceAdvisor繼承了AbstractBeanFactoryPointcutAdvisor,重寫了Pointcut getPointcut()方法。
使用自定義的切點(diǎn)類CacheOperationSourcePointcut來作為切面的切點(diǎn)。而里面需要用到CacheOperationSource和ClassFilter。在BeanFactoryCacheOperationSourceAdvisor實(shí)例化時(shí)就已經(jīng)設(shè)置。
而上面又執(zhí)行了advisor.setAdvice(cacheInterceptor); 其實(shí)就是對(duì)這個(gè)切點(diǎn)添加了一個(gè)緩存攔截器,所以核心邏輯就在攔截器里面。
先再來看一下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;
        // 重點(diǎn):解析集合從SpringCacheAnnotationParser中獲取,這個(gè)解析類就是解析注解的核心
        this.annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
    }
    
    // ...此處省略一萬行代碼
    // 判斷是否時(shí)候選類
    @Override
    public boolean isCandidateClass(Class<?> targetClass) {
        for (CacheAnnotationParser parser : this.annotationParsers) {
            if (parser.isCandidateClass(targetClass)) {
                return true;
            }
        }
        return false;
    }
    // 重點(diǎn):查找類級(jí)別的CacheOperation列表,就是看標(biāo)注在類上的@Cacheable,@CacheEvict的集合
    @Override
    @Nullable
    protected Collection<CacheOperation> findCacheOperations(Class<?> clazz) {
        return determineCacheOperations(parser -> parser.parseCacheAnnotations(clazz));
    }
    // 重點(diǎn):查找方法級(jí)別的CacheOperation列表,就是看標(biāo)注在方法上的@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);
    }
    // 解析類級(jí)別的注解,封裝為CacheOperation集合
    @Override
    @Nullable
    public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) {
        DefaultCacheConfig defaultConfig = new DefaultCacheConfig(type);
        return parseCacheAnnotations(defaultConfig, type);
    }
    // 解析方法級(jí)別的注解,封裝為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;
    }
    // ...此處省略了一萬行代碼,基本這個(gè)類都是解析這些注解并封裝為CacheOperation集合
}所以,SpringCacheAnnotationParser的作用就是將這些注解解析出來,并且封裝為Collection<CacheOperation>,供其他地方使用。
ProxyCachingConfiguration總的來說就是聲明了一個(gè)SpringCacheAnnotationParser和一個(gè)CacheInterceptor。在使用自定義的切點(diǎn)類,在切點(diǎn)前后切入一個(gè)CacheInterceptor來實(shí)現(xiàn)緩存的邏輯。
所以我們就找到的緩存的核心類CacheInterceptor,并且在構(gòu)造攔截器時(shí),傳入了cacheManager作為緩存管理。
2.1.2、分析CacheInterceptor類
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {
    // 攔截原始方法的執(zhí)行,在方法前后增加橫切邏輯
    @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 {
            // 調(diào)用父類的execute方法,實(shí)現(xiàn)緩存的邏輯
            return execute(aopAllianceInvoker, target, method, invocation.getArguments());
        }
        catch (CacheOperationInvoker.ThrowableWrapper th) {
            throw th.getOriginal();
        }
    }
}可以看到,這個(gè)類很簡單,就是拿到原方法的invoke,然后通過父類CacheAspectSupport的execute方法實(shí)現(xiàn)緩存邏輯。
關(guān)注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已經(jīng)被初始化了,則調(diào)用相應(yīng)的緩存增強(qiáng)
        if (this.initialized) {
            Class<?> targetClass = getTargetClass(target);
            CacheOperationSource cacheOperationSource = getCacheOperationSource();
            if (cacheOperationSource != null) {
                // 通過CacheOperationSource,獲取所有的CacheOperation列表(就是那一堆標(biāo)有緩存注解的類和方法的集合)
                Collection<CacheOperation> operations = cacheOperationSource.getCacheOperations(method, targetClass);
                if (!CollectionUtils.isEmpty(operations)) {
                    // 調(diào)用重載的execute方法
                    return execute(invoker, method,
                            new CacheOperationContexts(operations, method, args, target, targetClass));
                }
            }
        }
        // 否則,執(zhí)行原方法返回即可
        return invoker.invoke();
    }
    // 執(zhí)行方法(核心)
    @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注解、并且標(biāo)記為在調(diào)用前執(zhí)行,調(diào)用processCacheEvicts進(jìn)行緩存清除操作
        processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
                CacheOperationExpressionEvaluator.NO_RESULT);
        // 如果存在Cacheable注解、調(diào)用findCachedItem查詢緩存
        Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));
        // 如果沒有命中緩存,則調(diào)用cachePutRequests,存儲(chǔ)在List<CachePutRequest>中,后續(xù)執(zhí)行原始方法后會(huì)寫入緩存
        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 {
            // 調(diào)用原始方法作為返回值
            returnValue = invokeOperation(invoker);
            // 將原始方法的返回值作為緩存值
            cacheValue = unwrapReturnValue(returnValue);
        }
        // 如果有@CachePut注解,則新增到cachePutRequests
        collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
        // 緩存未命中或者存在@CachePut注解,調(diào)用CachePutRequest的apply方法將數(shù)據(jù)寫入緩存
        for (CachePutRequest cachePutRequest : cachePutRequests) {
            cachePutRequest.apply(cacheValue);
        }
        // 如果有@CacheEvict注解,并且標(biāo)記為在調(diào)用后執(zhí)行,則還需要執(zhí)行清除緩存操作
        processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
        return returnValue;
    }
    // 此處省略一萬行代碼
}總結(jié)來說,
- 如果存在@CacheEvict注解,并且標(biāo)記在方法執(zhí)行前執(zhí)行,就執(zhí)行清除緩存相關(guān)操作。
 - 使用findCachedItem獲取緩存,緩存沒有命中,加入collectPutRequests,后續(xù)進(jìn)行寫入緩存操作。
 - 如果命中緩存并且沒有@CachePut注解,獲取命中的值作為方法的返回值
 - 如果沒有命中,或者包含了@CachePut注解,加入collectPutRequests,后續(xù)進(jìn)行寫入緩存操作。
 - 遍歷cachePutRequests,將需要寫入緩存的數(shù)據(jù)寫入緩存
 - 如果存在@CacheEvict注解,并且標(biāo)記在方法執(zhí)行后執(zhí)行,就執(zhí)行清除緩存相關(guān)操作。
 
還沒完呢,因?yàn)槲覀兌x的CacheManager怎么沒有用到呢?我們繼續(xù)跟蹤下去,以get緩存方法為例子分析。
關(guān)注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);
            // 根據(jù)生成的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;
}關(guān)注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;
}關(guān)注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
    }
}我們發(fā)現(xiàn),最終是通過Cache接口的get方法去獲取緩存的,那么我們只要知道Cache集合對(duì)象是在哪里傳入進(jìn)來的就清楚了整個(gè)邏輯。
重新回到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)) {
                // 這里創(chuàng)建了一個(gè)CacheOperationContexts,我們有理由猜測CacheOperationContext.getCaches方法就是在這里面
                return execute(invoker, method,
                        new CacheOperationContexts(operations, method, args, target, targetClass));
            }
        }
    }
    return invoker.invoke();
}跟蹤C(jī)acheOperationContexts
private class CacheOperationContexts {
    // 就是一個(gè)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) {
        // 根據(jù)CacheOperation集合,方法,參數(shù)創(chuàng)建了一個(gè)CacheOperationContext集合
        this.contexts = new LinkedMultiValueMap<>(operations.size());
        for (CacheOperation op : operations) {
            // 重點(diǎn):getOperationContext是具體創(chuàng)建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;
    }
    
    // ...此處省略了一萬行代碼
}關(guān)注getOperationContext創(chuàng)建CacheOperationContext
protected CacheOperationContext getOperationContext(
        CacheOperation operation, Method method, Object[] args, Object target, Class<?> targetClass) {
    
    CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass);
    // 其實(shí)就是實(shí)例化一個(gè)CacheOperationContext
    return new CacheOperationContext(metadata, args, target);
}其實(shí)就是拿到CacheOperationMetadata(CacheOperation的元數(shù)據(jù)信息),然后傳給CacheOperationContext進(jìn)行實(shí)例化CacheOperationContext。
關(guān)注CacheOperationContext的構(gòu)造方法
上面實(shí)例化了CacheOperationContext,所以其構(gòu)造方法內(nèi)一定做了寫什么事情。比如初始化操作。
// 緩存的集合
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);
}關(guān)注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;
}關(guān)注CacheResolver以及實(shí)現(xiàn)類
@FunctionalInterface
public interface CacheResolver {
	// 根據(jù)CacheOperationInvocationContext獲取緩存集合
	Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
}CacheResolver的抽象實(shí)現(xiàn)類AbstractCacheResolver
public abstract class AbstractCacheResolver implements CacheResolver, InitializingBean {
    // 這里就有CacheManager(緩存管理器)
	@Nullable
	private CacheManager cacheManager;
	
	protected AbstractCacheResolver() {
	}
	
	// 構(gòu)造注入
	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默認(rèn)使用SimpleCacheManager,我們注入了CustomRedisCacheManager, 所以會(huì)調(diào)用CustomRedisCacheManager的getCache方法獲取緩存。
而getCache方法在父類AbstractCacheManager已經(jīng)實(shí)現(xiàn)了。
// SpringCache最底層的數(shù)據(jù)結(jié)構(gòu)就是以一個(gè)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;
    }
    // 獲取不到,使用雙重檢測所寫入數(shù)據(jù)到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的源碼分析就到此為止了。















 
 
 



















 
 
 
 