Spring Cache基础组件 Cache

相关阅读

简介

缓存接口,定义缓存操作;

核心代码

/**
 * 返回缓存标识符
 */
String getName();

/**
 * 返回底层缓存提供器
 */
Object getNativeCache();

/**
 * ValueWrapper方式返回缓存中指定键映射的值(值本身可能为null),值不存在则返回null
 */
@Nullable
ValueWrapper get(Object key);

/**
 * 返回缓存中指定键映射的值,值不存在则返回null;无法区分值本身为null的情况
 */
@Nullable
<T> T get(Object key, @Nullable Class<T> type);

/**
 * 如果缓存存在,则返回;否则从valueLoader获取值进行缓存并返回
 */
@Nullable
<T> T get(Object key, Callable<T> valueLoader);

/**
 * 缓存键和值的映射关系,如果存在键的映射关系,则新值替换旧值
 * 实际动作可能以异步或者延迟的方式执行,随后的查找动作可能看不到新映射关系
 * putIfAbsent保证立即注册
 */
void put(Object key, @Nullable Object value)

/**
 * 如果不存在键的的映射关系,就原子方式缓存键和值的映射关系
 * 期望该键在后续的查找时立即可见
 */
@Nullable
default ValueWrapper putIfAbsent(Object key, @Nullable Object value)

/**
 * 如果存在键的映射关系,则清除
 * 实际动作可能以异步或者延迟的方式执行,随后的查找动作可能看到原映射关系
 * evictIfPresent保证立即清除
 */
void evict(Object key);

/**
 * 如果存在键的映射关系,则清除;期望该键在后续的查找时立即不可见
 */
default boolean evictIfPresent(Object key)

/**
 * 清除缓存中所有映射关系
 * 实际动作可能以异步或者延迟的方式执行,随后的查找动作可能看到原映射关系
 * invalidate保证立即清除
 */
void clear();

/**
 * 清除缓存中所有映射关系;期望所有键在后续的查找时立即不可见
 */
default boolean invalidate()

实现子类

public interface Cache
    public class NoOpCache implements Cache
    public abstract class AbstractValueAdaptingCache implements Cache
        public class ConcurrentMapCache extends AbstractValueAdaptingCache
        public class RedisCache extends AbstractValueAdaptingCache

NoOpCache

简介

不做任何的缓存操作,适合禁用缓存的实现;
简单的接收参数,但不存储;

核心代码

// 缓存名称
private final String name;


/**
 * 构造方法
 */
public NoOpCache(String name) {
    Assert.notNull(name, "Cache name must not be null");
    this.name = name;
}

@Override
public String getName() {
    return this.name;
}

@Override
public Object getNativeCache() {
    return this;
}

@Override
@Nullable
public ValueWrapper get(Object key) {
    return null;
}

@Override
@Nullable
public <T> T get(Object key, @Nullable Class<T> type) {
    return null;
}

@Override
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
    try {
        return valueLoader.call();
    }
    catch (Exception ex) {
        throw new ValueRetrievalException(key, valueLoader, ex);
    }
}

@Override
public void put(Object key, @Nullable Object value) {
}

@Override
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
    return null;
}

@Override
public void evict(Object key) {
}

@Override
public boolean evictIfPresent(Object key) {
    return false;
}

@Override
public void clear() {
}

@Override
public boolean invalidate() {
    return false;
}

AbstractValueAdaptingCache

简介

Cache实现的通用基类,需要考虑null(或者其他的特殊值)的调整;

核心代码

// 是否允许null值
// 如果允许,则将nul转成NullValue.INSTANCE进行存储
// 否则,直接抛出IllegalArgumentException异常
private final boolean allowNullValues;


/**
 * 构造方法
 */
protected AbstractValueAdaptingCache(boolean allowNullValues) {
     this.allowNullValues = allowNullValues;
}

/**
 * 对存储的null值做特殊处理
 */
@Nullable
protected Object fromStoreValue(@Nullable Object storeValue) {
    if (this.allowNullValues && storeValue == NullValue.INSTANCE) {
        // 转换null值
        return null;
    }
    return storeValue;
}

/**
 * 转换成存储的值
 */
protected Object toStoreValue(@Nullable Object userValue) {
    if (userValue == null) {
        if (this.allowNullValues) {
            // 转换null值
            return NullValue.INSTANCE;
        }
        throw new IllegalArgumentException(
            "Cache '" + getName() + "' is configured to not allow null values but null was provided");
    }
    return userValue;
}

/**
 * 查找指定键的值
 * 算法细节,由子类实现
 */
@Nullable
protected abstract Object lookup(Object key);

/**
 * 返回指定键的值的包装,若值不存在则返回null
 */
@Nullable
public ValueWrapper get(Object key) {
    return toValueWrapper(lookup(key));
}

/**
 * 返回值的包装,若值为null则直接返回null
 */
@Nullable
protected Cache.ValueWrapper toValueWrapper(@Nullable Object storeValue) {
    return (storeValue != null ? new SimpleValueWrapper(fromStoreValue(storeValue)) : null);
}

/**
 * 返回指定键的值,若值不存在则直接返回null
 */
@Nullable
public <T> T get(Object key, @Nullable Class<T> type) {
    Object value = fromStoreValue(lookup(key));
    if (value != null && type != null && !type.isInstance(value)) {
        throw new IllegalStateException(
            "Cached value is not of required type [" + type.getName() + "]: " + value);
    }
    return (T) value;
}

ConcurrentMapCache

简介

基于ConcurrentMapCache实现,内部使用ConcurrentMap存储缓存数据,支持值序列化操作,可由构造器参数传入,默认为null;

核心代码

// 缓存名称
private final String name;
// 缓存容器
private final ConcurrentMap<Object, Object> store;
// 序列化器
@Nullable
private final SerializationDelegate serialization;


/**
 * 重写AbstractValueAdaptingCache的toStoreValue/fromStoreValue方法,支持序列化操作
 */
@Override
protected Object toStoreValue(@Nullable Object userValue) {
    // 调用父类方法拿到经过转换后的值
    Object storeValue = super.toStoreValue(userValue);
    if (this.serialization != null) {
        try {
            // 对转换后的值进行序列化
            return this.serialization.serializeToByteArray(storeValue);
        }
        catch (Throwable ex) {
            throw new IllegalArgumentException("Failed to serialize cache value '" + userValue +
                "'. Does it implement Serializable?", ex);
        }
    }
    else {
        // 无需序列化,直接返回
        return storeValue;
    }
}

/**
 * 对存储的null值做特殊处理
 */
@Override
protected Object fromStoreValue(@Nullable Object storeValue) {
    if (storeValue != null && this.serialization != null) {
        try {
            // 将反序列化后的值进行转换后返回
            return super.fromStoreValue(this.serialization.deserializeFromByteArray((byte[]) storeValue));
        }
        catch (Throwable ex) {
            throw new IllegalArgumentException("Failed to deserialize cache value '" + storeValue + "'", ex);
        }
    }
    else {
        // 无需反序列化,直接进行转换返回
        return super.fromStoreValue(storeValue);
    }
}

/**
 * 从ConcurrentMap中取值
 */
@Nullable
protected Object lookup(Object key) {
    // 直接使用concurrentMap的查找方法
    return this.store.get(key);
}

/**
 * 获取指定键的值,若不存在则缓存valueLoader的值并返回
 */
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
    // 转换成原始的值
    return (T) fromStoreValue(this.store.computeIfAbsent(key, k -> {
         try {
             // 转换成存储的值
             return toStoreValue(valueLoader.call());
         }
         catch (Throwable ex) {
             throw new ValueRetrievalException(key, valueLoader, ex);
         }
    }));
}

/**
 * 往ConcurrentMap中存值
 */
public void put(Object key, @Nullable Object value) {
    // 需要将原始值转换成存储值
    this.store.put(key, toStoreValue(value));
}

/**
 * 若指定键不存在则往ConcurrentMap中存值
 * 返回ConcurrentMap中指定键的旧值,不存在则为null
 */
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
    Object existing = this.store.putIfAbsent(key, toStoreValue(value));
    return toValueWrapper(existing);
}

/**
 * 从ConcurrentMap中删值
 */
public void evict(Object key) {
    this.store.remove(key);
}

/**
 * 若存在则从ConcurrentMap中删值
 */
public boolean evictIfPresent(Object key) {
    return (this.store.remove(key) != null);
}

/**
 * 清空ConcurrentMap
 */
public void clear() {
    this.store.clear();
}

/**
 * 清除缓存中所有映射关系
 */
public boolean invalidate() {
    boolean notEmpty = !this.store.isEmpty();
    // 清空ConcurrentMap
    this.store.clear();
    return notEmpty;
}

RedisCache

简介

基于Redis的Cache实现;

核心代码

// 空值
private static final byte[] BINARY_NULL_VALUE = RedisSerializer.java().serialize(NullValue.INSTANCE);
// 缓存名称
private final String name;
// redis缓存操作
private final RedisCacheWriter cacheWriter;
// redis缓存配置
private final RedisCacheConfiguration cacheConfig;
// 转换服务
private final ConversionService conversionService;


/**
 * 预处理值
 */
@Nullable
protected Object preProcessCacheValue(@Nullable Object value) {
    if (value != null) {
        return value;
    }
    // 不直接存储null值,对null值做特殊转换
    return isAllowNullValues() ? NullValue.INSTANCE : null;
}

/**
 * 序列化键
 */
protected byte[] serializeCacheKey(String cacheKey) {
    return ByteUtils.getBytes(cacheConfig.getKeySerializationPair().write(cacheKey));
}

/**
 * 序列化值
 */
protected byte[] serializeCacheValue(Object value) {
    if (isAllowNullValues() && value instanceof NullValue) {
        // 不对null值做序列化
        return BINARY_NULL_VALUE;
    }
    return ByteUtils.getBytes(cacheConfig.getValueSerializationPair().write(value));
}

/**
 * 反序列化值
 */
@Nullable
protected Object deserializeCacheValue(byte[] value) {
    if (isAllowNullValues() && ObjectUtils.nullSafeEquals(value, BINARY_NULL_VALUE)) {
        // 不对null值做反序列化
        return NullValue.INSTANCE;
    }
    return cacheConfig.getValueSerializationPair().read(ByteBuffer.wrap(value));
}

/**
 * 从redis中查找缓存
 */
protected Object lookup(Object key) {
    byte[] value = cacheWriter.get(name, createAndConvertCacheKey(key));
    if (value == null) {
        return null;
    }
    // 反序列化值
    return deserializeCacheValue(value);
}

/**
 * 从redis中获取缓存,若不存在则缓存valueLoader的值并返回
 */
public <T> T get(Object key, Callable<T> valueLoader) {
    ValueWrapper result = get(key);
    if (result != null) {
        // 若存在则返回
        return (T) result.get();
    }
    // 同步执行,缓存valueLoader的值并返回
    return getSynchronized(key, valueLoader);
}

/**
 * 同步执行,从redis获取缓存,若不存在则缓存valueLoader的值并返回
 */
private synchronized <T> T getSynchronized(Object key, Callable<T> valueLoader) {
    ValueWrapper result = get(key);
    if (result != null) {
        // 若存在则直接返回
        return (T) result.get();
    }
    T value;
    try {
        value = valueLoader.call();
    } catch (Exception e) {
        throw new ValueRetrievalException(key, valueLoader, e);
    }
    // 存入缓存
    put(key, value);
    return value;
}

/**
 * 缓存存入redis
 */
public void put(Object key, @Nullable Object value) {
    Object cacheValue = preProcessCacheValue(value);
    if (!isAllowNullValues() && cacheValue == null) {
        throw new IllegalArgumentException(String.format(
            "Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=\"#result == null\")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.", name));
    }
    cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl());
}

/**
 * 若指定键不存在则往redis存入值
 */
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
    Object cacheValue = preProcessCacheValue(value);
    if (!isAllowNullValues() && cacheValue == null) {
        // 不允许null并且新值为null,则直接返回原值,原值不存在则返回null
        return get(key);
    }
    byte[] result = cacheWriter.putIfAbsent(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl());
    if (result == null) {
        // 原值不存在则返回null
        return null;
    }
    // 返回原值的包装
    return new SimpleValueWrapper(fromStoreValue(deserializeCacheValue(result)));
}

/**
 * 从redis删值
 */
public void evict(Object key) {
    cacheWriter.remove(name, createAndConvertCacheKey(key));
}

/**
 * 清空redis缓存
 */
public void clear() {
    byte[] pattern = conversionService.convert(createCacheKey("*"), byte[].class);
    cacheWriter.clean(name, pattern);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值