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);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章