Spring 缓存注解解析过程

Posted 竺旭东

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 缓存注解解析过程相关的知识,希望对你有一定的参考价值。

Spring 缓存注解解析过程

通过 SpringCacheAnnotationParser 的 parseCacheAnnotations 方法解析指定方法或类上的缓存注解,
@Cacheable 注解将被解析为 CacheableOperation 操作,
@CachePut 注解将被解析为 CachePutOperation 操作,
@CacheEvict 注解将被解析为 CacheEvictOperation 操作。

缓存注解

/**
 *  启用Spring以注解驱动的缓存管理功能
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {
    /**
     *  是否启用 CGLIB 类代理,默认是 JDK 动态代理
     */
    boolean proxyTargetClass() default false;

    /**
     *  指示如何应用缓存通知,默认是 JDK Proxy
     */
    AdviceMode mode() default AdviceMode.PROXY;

    /**
     *  当多个 Adviser 将通知织入连接点时,缓存通知的优先级
     */
    int order() default Ordered.LOWEST_PRECEDENCE;
}


/**
 *  在类级别设置共享的缓存配置信息
 * @since 4.1
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CacheConfig {
    /**
     *  默认缓存名称
     */
    String[] cacheNames() default {};

    /**
     *  默认的键生成器 bean 名称
     *  org.springframework.cache.interceptor.KeyGenerator
     */
    String keyGenerator() default "";

    /**
     *  默认的缓存管理器 bean 名称
     *  org.springframework.cache.CacheManager
     */
    String cacheManager() default "";

    /**
     *  默认的缓存解析器 bean 名称
     *  org.springframework.cache.interceptor.CacheResolver
     */
    String cacheResolver() default "";
}

/**
 *  表明类中单个方法【作用于方法】或所有方法的返回值【作用于类】能被缓存
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {

    /**
     *  cacheNames 别名
     */
    @AliasFor("cacheNames")
    String[] value() default {};

    /**
     *  关联缓存名称数组
     * @since 4.2
     */
    @AliasFor("value")
    String[] cacheNames() default {};

    /**
     *  动态计算缓存键的 SpEL 表达式
     */
    String key() default "";

    /**
     *  缓存键生成器 bean 名称
     */
    String keyGenerator() default "";

    /**
     *  缓存管理器 bean 名称
     */
    String cacheManager() default "";

    /**
     *  缓存解析器 bean 名称
     */
    String cacheResolver() default "";

    /**
     *  缓存操作的生效条件【SpEL 表达式】,不指定默认生效
     */
    String condition() default "";

    /**
     *  否决方法缓存的条件【SpEL 表达式】,默认不匹配【返回 true 表示不缓存】
     */
    String unless() default "";

    /**
     *  多线程调用方法时,是否执行同步调用
     * <ol>
     * <li>{@link #unless()} is not supported</li>
     * <li>Only one cache may be specified</li>
     * <li>No other cache-related operation can be combined</li>
     * </ol>
     * @since 4.3
     */
    boolean sync() default false;
}


/**
 *  指定的方法调用或类中所有方法调用,需要执行 CachePut 操作将结果值进行缓存
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CachePut {
    /**
     *  cacheNames 别名
     */
    @AliasFor("cacheNames")
    String[] value() default {};

    /**
     *  关联缓存名称数组
     * @since 4.2
     */
    @AliasFor("value")
    String[] cacheNames() default {};

    /**
     *  动态计算缓存键的 SpEL 表达式
     */
    String key() default "";

    /**
     *  缓存键生成器 bean 名称
     */
    String keyGenerator() default "";

    /**
     *  缓存管理器 bean 名称
     */
    String cacheManager() default "";

    /**
     *  缓存解析器 bean 名称
     */
    String cacheResolver() default "";

    /**
     *  缓存操作的生效条件【SpEL 表达式】,不指定默认生效
     */
    String condition() default "";

    /**
     *  否决方法缓存的条件【SpEL 表达式】,默认不匹配【返回 true 表示不缓存】
     *  @since 3.2
     */
    String unless() default "";
}


/**
 *  指定的方法调用或所有方法调用,需要执行一个缓存清除操作。
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CacheEvict {
    /**
     *  cacheNames 别名
     */
    @AliasFor("cacheNames")
    String[] value() default {};

    /**
     *  关联缓存名称数组
     * @since 4.2
     */
    @AliasFor("value")
    String[] cacheNames() default {};

    /**
     *  动态计算缓存键的 SpEL 表达式
     */
    String key() default "";

    /**
     *  缓存键生成器 bean 名称
     */
    String keyGenerator() default "";

    /**
     *  缓存管理器 bean 名称
     */
    String cacheManager() default "";

    /**
     *  缓存解析器 bean 名称
     */
    String cacheResolver() default "";

    /**
     *  缓存操作的生效条件【SpEL 表达式】,不指定默认生效
     */
    String condition() default "";

    /**
     *  是否删除缓存中的所有条目,默认只删除缓存键关联的条目
     */
    boolean allEntries() default false;

    /**
     *  缓存清除操作是否需要在方法调用前执行
     */
    boolean beforeInvocation() default false;
}

缓存注解解析器

/**
 *  用于解析缓存注解的策略接口
 */
public interface CacheAnnotationParser {

    /**
     *  基于注释类型解析指定类的缓存定义
     */
    @Nullable
    Collection<CacheOperation> parseCacheAnnotations(Class<?> type);

    /**
     *  基于注释类型解析指定方法的缓存定义
     */
    @Nullable
    Collection<CacheOperation> parseCacheAnnotations(Method method);
}

/**
 *  用于解析  @Caching、@Cacheable、@CacheEvict、@CachePut 注解的解析器
 */
@SuppressWarnings("serial")
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);
    }

    /**
     *  解析指定类上的缓存注解
     */
    @Override
    @Nullable
    public Collection<CacheOperation> parseCacheAnnotations(Class<?> type) {
        // 创建默认的缓存配置
        final DefaultCacheConfig defaultConfig = new DefaultCacheConfig(type);
        return parseCacheAnnotations(defaultConfig, type);
    }

    /**
     *  解析指定方法上的缓存注解
     */
    @Override
    @Nullable
    public Collection<CacheOperation> parseCacheAnnotations(Method method) {
        // 创建默认的缓存配置
        final DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass());
        return parseCacheAnnotations(defaultConfig, method);
    }

    /**
     *  基于默认的缓存配置解析缓存注解
     */
    @Nullable
    private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {
        final Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false);
        if (ops != null && ops.size() > 1) {
            // 如果发现多于 1 个缓存操作,则类中的缓存操作覆盖接口中的缓存操作
            final Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);
            if (localOps != null) {
                return localOps;
            }
        }
        return ops;
    }

    /**
     *  解析指定注解元素上的缓存注解
     *
     * @param cachingConfig 缓存配置
     * @param ae    注解元素
     * @param localOnly 是否只解析当前类中的缓存注解【缓存注解也可以在接口上使用】
     */
    @Nullable
    private Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae,
            boolean localOnly) {
        // 读取所有的缓存注解
        final 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);
        // 解析 Cacheable 注解
        anns.stream().filter(ann -> ann instanceof Cacheable)
        .forEach(ann -> ops.add(parseCacheableAnnotation(ae, cachingConfig, (Cacheable) ann)));
        // 解析 CacheEvict 注解
        anns.stream().filter(ann -> ann instanceof CacheEvict)
        .forEach(ann -> ops.add(parseEvictAnnotation(ae, cachingConfig, (CacheEvict) ann)));
        // 解析 CachePut 注解
        anns.stream().filter(ann -> ann instanceof CachePut)
        .forEach(ann -> ops.add(parsePutAnnotation(ae, cachingConfig, (CachePut) ann)));
        // 解析 Caching 注解
        anns.stream().filter(ann -> ann instanceof Caching)
        .forEach(ann -> parseCachingAnnotation(ae, cachingConfig, (Caching) ann, ops));
        return ops;
    }

    private CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig,
            Cacheable cacheable) {
        final CacheableOperation.Builder builder = new CacheableOperation.Builder();
        // 操作名称为注解元素的字符串表示
        builder.setName(ae.toString());
        builder.setCacheNames(cacheable.cacheNames());
        builder.setCondition(cacheable.condition());
        builder.setUnless(cacheable.unless());
        builder.setKey(cacheable.key());
        builder.setKeyGenerator(cacheable.keyGenerator());
        builder.setCacheManager(cacheable.cacheManager());
        builder.setCacheResolver(cacheable.cacheResolver());
        builder.setSync(cacheable.sync());
        // 尝试写入默认值
        defaultConfig.applyDefault(builder);
        final CacheableOperation op = builder.build();
        /**
         * 验证缓存操作
         * key 和 keyGenerator 不可同时配置
         * cacheManager 和 cacheResolver 不可同时配置
         */
        validateCacheOperation(ae, op);
        return op;
    }

    private CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig,
            CacheEvict cacheEvict) {
        final CacheEvictOperation.Builder builder = new CacheEvictOperation.Builder();
        builder.setName(ae.toString());
        builder.setCacheNames(cacheEvict.cacheNames());
        builder.setCondition(cacheEvict.condition());
        builder.setKey(cacheEvict.key());
        builder.setKeyGenerator(cacheEvict.keyGenerator());
        builder.setCacheManager(cacheEvict.cacheManager());
        builder.setCacheResolver(cacheEvict.cacheResolver());
        builder.setCacheWide(cacheEvict.allEntries());
        builder.setBeforeInvocation(cacheEvict.beforeInvocation());

        defaultConfig.applyDefault(builder);
        final CacheEvictOperation op = builder.build();
        validateCacheOperation(ae, op);

        return op;
    }

    private CacheOperation parsePutAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig,
            CachePut cachePut) {
        final CachePutOperation.Builder builder = new CachePutOperation.Builder();

        builder.setName(ae.toString());
        builder.setCacheNames(cachePut.cacheNames());
        builder.setCondition(cachePut.condition());
        builder.setUnless(cachePut.unless());
        builder.setKey(cachePut.key());
        builder.setKeyGenerator(cachePut.keyGenerator());
        builder.setCacheManager(cachePut.cacheManager());
        builder.setCacheResolver(cachePut.cacheResolver());

        defaultConfig.applyDefault(builder);
        final CachePutOperation op = builder.build();
        validateCacheOperation(ae, op);

        return op;
    }

    private void parseCachingAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Caching caching,
            Collection<CacheOperation> ops) {
        final Cacheable[] cacheables = caching.cacheable();
        for (final Cacheable cacheable : cacheables) {
            ops.add(parseCacheableAnnotation(ae, defaultConfig, cacheable));
        }
        final CacheEvict[] cacheEvicts = caching.evict();
        for (final CacheEvict cacheEvict : cacheEvicts) {
            ops.add(parseEvictAnnotation(ae, defaultConfig, cacheEvict));
        }
        final CachePut[] cachePuts = caching.put();
        for (final CachePut cachePut : cachePuts) {
            ops.add(parsePutAnnotation(ae, defaultConfig, cachePut));
        }
    }

    /**
     * Validates the specified {@link CacheOperation}.
     * <p>Throws an {@link IllegalStateException} if the state of the operation is
     * invalid. As there might be multiple sources for default values, this ensure
     * that the operation is in a proper state before being returned.
     * @param ae the annotated element of the cache operation
     * @param operation the {@link CacheOperation} to validate
     */
    private void validateCacheOperation(AnnotatedElement ae, CacheOperation operation) {
        if (StringUtils.hasText(operation.getKey()) && StringUtils.hasText(operation.getKeyGenerator())) {
            throw new IllegalStateException("Invalid cache annotation configuration on ‘" + ae.toString()
            + "‘. Both ‘key‘ and ‘keyGenerator‘ attributes have been set. "
            + "These attributes are mutually exclusive: either set the SpEL expression used to"
            + "compute the key at runtime or set the name of the KeyGenerator bean to use.");
        }
        if (StringUtils.hasText(operation.getCacheManager()) && StringUtils.hasText(operation.getCacheResolver())) {
            throw new IllegalStateException("Invalid cache annotation configuration on ‘" + ae.toString()
            + "‘. Both ‘cacheManager‘ and ‘cacheResolver‘ attributes have been set. "
            + "These attributes are mutually exclusive: the cache manager is used to configure a"
            + "default cache resolver if none is set. If a cache resolver is set, the cache manager"
            + "won‘t be used.");
        }
    }

    @Override
    public boolean equals(Object other) {
        return this == other || other instanceof SpringCacheAnnotationParser;
    }

    @Override
    public int hashCode() {
        return SpringCacheAnnotationParser.class.hashCode();
    }

    /**
     *  为给定的缓存操作集提供默认配置
     */
    private static class DefaultCacheConfig {
        /**
         *  目标类型
         */
        private final Class<?> target;
        /**
         *  缓存名称
         */
        @Nullable
        private String[] cacheNames;
        /**
         *  键生成器名称
         */
        @Nullable
        private String keyGenerator;
        /**
         *  缓存管理器名称
         */
        @Nullable
        private String cacheManager;
        /**
         *  缓存解析器名称
         */
        @Nullable
        private String cacheResolver;
        /**
         *  是否已经初始化
         */
        private boolean initialized = false;

        public DefaultCacheConfig(Class<?> target) {
            this.target = target;
        }

        /**
         * Apply the defaults to the specified {@link CacheOperation.Builder}.
         */
        public void applyDefault(CacheOperation.Builder builder) {
            if (!initialized) {
                // 查找目标类型上的 CacheConfig 注解配置,如果存在则写入默认配置
                final CacheConfig annotation = AnnotatedElementUtils.findMergedAnnotation(target, CacheConfig.class);
                if (annotation != null) {
                    cacheNames = annotation.cacheNames();
                    keyGenerator = annotation.keyGenerator();
                    cacheManager = annotation.cacheManager();
                    cacheResolver = annotation.cacheResolver();
                }
                initialized = true;
            }

            // 指定注解未设置缓存名称 && 默认配置不为 null && 写入默认配置
            if (builder.getCacheNames().isEmpty() && cacheNames != null) {
                builder.setCacheNames(cacheNames);
            }
            // 指定注解未指定键和键生成器 && 默认配置不为 null && 写入键生成器
            if (!StringUtils.hasText(builder.getKey()) && !StringUtils.hasText(builder.getKeyGenerator())
                    && StringUtils.hasText(keyGenerator)) {
                builder.setKeyGenerator(keyGenerator);
            }
            // 未指定缓存管理器和缓存解析器,则默认的 cacheResolver 优先级高于 cacheManager
            if (StringUtils.hasText(builder.getCacheManager()) || StringUtils.hasText(builder.getCacheResolver())) {
                // One of these is set so we should not inherit anything
            } else if (StringUtils.hasText(cacheResolver)) {
                builder.setCacheResolver(cacheResolver);
            } else if (StringUtils.hasText(cacheManager)) {
                builder.setCacheManager(cacheManager);
            }
        }
    }
}

缓存操作

/**
 *  所有缓存操作必须实现的基本接口
 */
public interface BasicOperation {
    /**
     *  返回与此操作关联的所有缓存名称
     */
    Set<String> getCacheNames();
}

/**
 *  缓存操作基础类
 */
public abstract class CacheOperation implements BasicOperation {
    /**
     *  操作名称
     */
    private final String name;
    /**
     *  关联缓存名称
     */
    private final Set<String> cacheNames;
    /**
     *  缓存键
     */
    private final String key;
    /**
     *  缓存键生成器名称
     */
    private final String keyGenerator;
    /**
     *  缓存管理器名称
     */
    private final String cacheManager;
    /**
     *  缓存解析器名称
     */
    private final String cacheResolver;
    /**
     *  缓存条件
     */
    private final String condition;
    /**
     *  操作的字符串表示
     */
    private final String toString;
}

/**
 *  对应于 @Cacheable 注解的操作
 */
public class CacheableOperation extends CacheOperation {
    /**
     *  缓存条件
     */
    @Nullable
    private final String unless;
    /**
     *  此操作是否是同步的
     */
    private final boolean sync;
}

/**
 *  对应于 @CacheEvict 注解的操作
 */
public class CacheEvictOperation extends CacheOperation {
    /**
     *  是否删除缓存中的所有条目
     */
    private final boolean cacheWide;
    /**
     *  是否在目标方法调用之前执行
     */
    private final boolean beforeInvocation;
}

/**
 * 对应于 @CachePut 注解的操作
 */
public class CachePutOperation extends CacheOperation {
    /**
     *  缓存条件
     */
    @Nullable
    private final String unless;
}

缓存操作源

/**
 * 被 CacheInterceptor 使用的缓存操作源
 */
public interface CacheOperationSource {

    /**
     *  获取目标类中指定方法的所有缓存操作
     */
    @Nullable
    Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass);

}

/**
 *  带兜底策略的缓存操作源,缓存注解解析顺序如下
 * 1. specific target method;
 * 2. target class;
 * 3. declaring method;
 * 4. declaring class/interface.
 */
public abstract class AbstractFallbackCacheOperationSource implements CacheOperationSource {
    /**
     * Canonical value held in cache to indicate no caching attribute was
     * found for this method and we don‘t need to look again.
     */
    private static final Collection<CacheOperation> NULL_CACHING_ATTRIBUTE = Collections.emptyList();

    protected final Log logger = LogFactory.getLog(getClass());

    /**
     *  缓存操作的缓存
     */
    private final Map<Object, Collection<CacheOperation>> attributeCache = new ConcurrentHashMap<>(1024);

    /**
     *  确定此方法调用的缓存属性
     */
    @Override
    @Nullable
    public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) {
        if (method.getDeclaringClass() == Object.class) {
            return null;
        }
        // 创建缓存键
        final Object cacheKey = getCacheKey(method, targetClass);
        // 读取操作缓存
        final Collection<CacheOperation> cached = attributeCache.get(cacheKey);

        // 1)如果存在则直接返回
        if (cached != null) {
            return cached != NULL_CACHING_ATTRIBUTE ? cached : null;
        }
        else {
            // 2)解析指定方法上的缓存操作并缓存
            final Collection<CacheOperation> cacheOps = computeCacheOperations(method, targetClass);
            if (cacheOps != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Adding cacheable method ‘" + method.getName() + "‘ with attribute: " + cacheOps);
                }
                attributeCache.put(cacheKey, cacheOps);
            }
            else {
                attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE);
            }
            return cacheOps;
        }
    }

    /**
     * Determine a cache key for the given method and target class.
     * <p>Must not produce same key for overloaded methods.
     * Must produce same key for different instances of the same method.
     * @param method the method (never {@code null})
     * @param targetClass the target class (may be {@code null})
     * @return the cache key (never {@code null})
     */
    protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
        return new MethodClassKey(method, targetClass);
    }

    @Nullable
    private Collection<CacheOperation> computeCacheOperations(Method method, @Nullable Class<?> targetClass) {
        // 是否只解析 public 方法的缓存注解【默认 false】
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        }

        /**
         *  The method may be on an interface, but we need attributes from the target class.
         *  If the target class is null, the method will be unchanged.
         */
        final Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

        // 1)First try is the method in the target class.
        Collection<CacheOperation> opDef = findCacheOperations(specificMethod);
        if (opDef != null) {
            return opDef;
        }

        // 2)Second try is the caching operation on the target class.
        opDef = findCacheOperations(specificMethod.getDeclaringClass());
        if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
            return opDef;
        }

        if (specificMethod != method) {
            // Fallback is to look at the original method.
            opDef = findCacheOperations(method);
            if (opDef != null) {
                return opDef;
            }
            // Last fallback is the class of the original method.
            opDef = findCacheOperations(method.getDeclaringClass());
            if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
                return opDef;
            }
        }

        return null;
    }

    @Nullable
    protected abstract Collection<CacheOperation> findCacheOperations(Class<?> clazz);

    @Nullable
    protected abstract Collection<CacheOperation> findCacheOperations(Method method);

    protected boolean allowPublicMethodsOnly() {
        return false;
    }
}

@SuppressWarnings("serial")
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {
    /**
     *  是否只解析 public 方法,默认为 true
     */
    private final boolean publicMethodsOnly;
    /**
     *  缓存注解解析器
     */
    private final Set<CacheAnnotationParser> annotationParsers;

    public AnnotationCacheOperationSource() {
        this(true);
    }

    public AnnotationCacheOperationSource(boolean publicMethodsOnly) {
        this.publicMethodsOnly = publicMethodsOnly;
        annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
    }

    public AnnotationCacheOperationSource(CacheAnnotationParser annotationParser) {
        publicMethodsOnly = true;
        Assert.notNull(annotationParser, "CacheAnnotationParser must not be null");
        annotationParsers = Collections.singleton(annotationParser);
    }

    public AnnotationCacheOperationSource(CacheAnnotationParser... annotationParsers) {
        publicMethodsOnly = true;
        Assert.notEmpty(annotationParsers, "At least one CacheAnnotationParser needs to be specified");
        this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
    }

    public AnnotationCacheOperationSource(Set<CacheAnnotationParser> annotationParsers) {
        publicMethodsOnly = true;
        Assert.notEmpty(annotationParsers, "At least one CacheAnnotationParser needs to be specified");
        this.annotationParsers = annotationParsers;
    }

    @Override
    @Nullable
    protected Collection<CacheOperation> findCacheOperations(Class<?> clazz) {
        return determineCacheOperations(parser -> parser.parseCacheAnnotations(clazz));
    }

    @Override
    @Nullable
    protected Collection<CacheOperation> findCacheOperations(Method method) {
        return determineCacheOperations(parser -> parser.parseCacheAnnotations(method));
    }

    /**
     *  解析缓存注解并转换为 CacheOperation
     */
    @Nullable
    protected Collection<CacheOperation> determineCacheOperations(CacheOperationProvider provider) {
        Collection<CacheOperation> ops = null;
        for (final CacheAnnotationParser annotationParser : annotationParsers) {
            final Collection<CacheOperation> annOps = provider.getCacheOperations(annotationParser);
            if (annOps != null) {
                if (ops == null) {
                    ops = annOps;
                }
                else {
                    final Collection<CacheOperation> combined = new ArrayList<>(ops.size() + annOps.size());
                    combined.addAll(ops);
                    combined.addAll(annOps);
                    ops = combined;
                }
            }
        }
        return ops;
    }

    @Override
    protected boolean allowPublicMethodsOnly() {
        return publicMethodsOnly;
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof AnnotationCacheOperationSource)) {
            return false;
        }
        final AnnotationCacheOperationSource otherCos = (AnnotationCacheOperationSource) other;
        return annotationParsers.equals(otherCos.annotationParsers) &&
                publicMethodsOnly == otherCos.publicMethodsOnly;
    }

    @Override
    public int hashCode() {
        return annotationParsers.hashCode();
    }

    @FunctionalInterface
    protected interface CacheOperationProvider {
        /**
         *  返回指定缓存解析解析成功的缓存操作
         */
        @Nullable
        Collection<CacheOperation> getCacheOperations(CacheAnnotationParser parser);
    }

}

以上是关于Spring 缓存注解解析过程的主要内容,如果未能解决你的问题,请参考以下文章

@PostConstruct

Spring Bean定义的加载解析过程之注解的过程

1-spring xml 和 注解 解析过程

Spring启动后扫描解析注解的过程

spring加载bean流程解析

Spring MVC注解Controller源码流程解析---请求匹配中的容错处理