Spring Cache基础组件 CacheOperationSource

相关阅读

简介

解析缓存动作的接口,由CacheInterceptor调用;
实现类知道如何从配置、源级别或者其它地方元数据获取缓存动作定义;

核心代码

/**
 * 判断是否需要对当前类的所有方法进行解析
 */
default boolean isCandidateClass(Class<?> targetClass) {
    return true;
}

/**
 * 返回指定类的指定方法上所有SpringCache注解定义的缓存动作
 */
@Nullable
Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass);

实现子类

public interface CacheOperationSource
    public abstract class AbstractFallbackCacheOperationSource implements CacheOperationSource
        public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable

AbstractFallbackCacheOperationSource

简介

定义了getCacheOperations方法的算法模板,并提供两个抽象方法由子类实现算法细节;

核心代码

// null值的替代,ConcurrentHashMap不存null值
private static final Collection<CacheOperation> NULL_CACHING_ATTRIBUTE = Collections.emptyList()
// CacheOperation缓存集合
private final Map<Object, Collection<CacheOperation>> attributeCache = new ConcurrentHashMap<>(1024);


/**
 * 获取指定方法的缓存动作集合
 * 算法模板
 */
@Nullable
public Collection<CacheOperation> getCacheOperations(Method method, @Nullable Class<?> targetClass) {
    // Object的方法没有缓存
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }
    // 根据类和方法生成缓存KEY
    Object cacheKey = getCacheKey(method, targetClass);
    // 根据KEY,查缓存MAP,如果已经解析过,则直接返回
    Collection<CacheOperation> cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        return (cached != NULL_CACHING_ATTRIBUTE ? cached : null);
    }
    else {
        // 缓存MAP中不存在,则需要解析指定类的指定方法上的SpringCache动作
        Collection<CacheOperation> cacheOps = computeCacheOperations(method, targetClass);
        // 将解析结果存入缓存MAP,以便下次直接返回
        if (cacheOps != null) {
            if (logger.isTraceEnabled()) {
            logger.trace("Adding cacheable method '" + method.getName() + "' with attribute: " + cacheOps);
            }
            this.attributeCache.put(cacheKey, cacheOps);
        }
        else {
            this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE);
        }
        return cacheOps;
    }
}

/**
 * 根据类和方法生成缓存KEY
 * 要求:
 *   1. 重载的方法的KEY要不同
 *   2. 同一类的不同实例的方法的KEY要相同
 */
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
    return new MethodClassKey(method, targetClass);
}

/**
 * 解析SpringCache动作
 */
@Nullable
private Collection<CacheOperation> computeCacheOperations(Method method, @Nullable Class<?> targetClass) {
    // 如果方法不是public并且只允许public有缓存动作
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }
    // 找到method的真正实现
    // 例如:Ifoo.bar(), target is DefaultFoo(implements Ifoo), so method is DefaultFoo.bar()
    // 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.
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

    // 第一次解析,根据method
    // First try is the method in the target class.
    Collection<CacheOperation> opDef = findCacheOperations(specificMethod);
    if (opDef != null) {
        return opDef;
    }
    
    // 第二次解析,根据target class
    // Second try is the caching operation on the target class.
    opDef = findCacheOperations(specificMethod.getDeclaringClass());
    if (opDef != null && ClassUtils.isUserLevelMethod(method)) {
        return opDef;
    }

    // 如果被解析的method不是原始入参,那么根据原始入参method再走一遍解析过程
    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;
}

/**
 * 是否只支持public方法拥有SpringCache动作
 */
protected boolean allowPublicMethodsOnly() {
    return false;
}

/**
 * 获取类上的SpringCache动作
 * 算法细节,由子类实现
 */
@Nullable
protected abstract Collection<CacheOperation> findCacheOperations(Class<?> clazz);

/**
 * 获取方法上的SpringCache动作
 * 算法细节,由子类实现
 */
@Nullable
protected abstract Collection<CacheOperation> findCacheOperations(Method method);

AnnotationCacheOperationSource

简介

CacheOperationSource接口的实现,解析注释格式的缓存元数据;

核心代码

// 是否只允许public方法拥有SpringCache,默认true
private final boolean publicMethodsOnly;
// 解析器集合,默认只包括SpringCacheAnnotationParser
private final Set<CacheAnnotationParser> annotationParsers;


/**
 * 构造方法
 */
public AnnotationCacheOperationSource() {
     this(true);
}

/**
 * 构造方法
 */
public AnnotationCacheOperationSource(boolean publicMethodsOnly) {
     this.publicMethodsOnly = publicMethodsOnly;
     this.annotationParsers = Collections.singleton(new     SpringCacheAnnotationParser());
}

/**
 * 回调模式实现根据class获取类上的SpringCache动作
 */
@Nullable
protected Collection<CacheOperation> findCacheOperations(Class<?> clazz) {
    return determineCacheOperations(parser -> parser.parseCacheAnnotations(clazz));
}

/**
 * 回调模式实现根据method获取方法上的SpringCache动作
 */
@Nullable
protected Collection<CacheOperation> findCacheOperations(Method method) {
    return determineCacheOperations(parser -> parser.parseCacheAnnotations(method));
}

/**
 * 解析SpringCache动作
 */
@Nullable
protected Collection<CacheOperation> determineCacheOperations(CacheOperationProvider provider) {
    Collection<CacheOperation> ops = null;
    // 遍历解析器集合,综合所有解析器的结果
    for (CacheAnnotationParser parser : this.annotationParsers) {
        Collection<CacheOperation> annOps = provider.getCacheOperations(parser);
        if (annOps != null) {
            if (ops == null) {
                ops = annOps;
            }
            else {
                // 合并已有结果
                Collection<CacheOperation> combined = new ArrayList<>(ops.size() + annOps.size());
                combined.addAll(ops);
                combined.addAll(annOps);
                ops = combined;
            }
        }
    }
    return ops;
}

/**
 * 是否只允许public方法拥有SpringCache动作
 */
protected boolean allowPublicMethodsOnly() {
    return this.publicMethodsOnly;
}

/**
 * 判断是否需要对当前类的所有方法进行解析
 */
public boolean isCandidateClass(Class<?> targetClass) {
    // 遍历解析器集合,只要满足其中一个就需要解析,否则不解析
    for (CacheAnnotationParser parser : this.annotationParsers) {
        if (parser.isCandidateClass(targetClass)) {
            return true;
        }
    }
    return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值