zoukankan      html  css  js  c++  java
  • 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);
        }
    
    }
    
  • 相关阅读:
    素数
    Java日期时间使用(转)
    mysql中函数(转)
    java环境配置
    volley三种基本请求图片的方式与Lru的基本使用:正常的加载+含有Lru缓存的加载+Volley控件networkImageview的使用
    Volley的三种基本用法StringRequest的Get和post用法以及JsonObjectRequest
    DOM生成&解析
    Pull生成&解析
    HDU.2503 a/b + c/d (分式化简)
    HDU.2503 a/b + c/d (分式化简)
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10322597.html
Copyright © 2011-2022 走看看