1.spring cache简介
spring对各种缓存技术进行了封装(包括concurrentMap,redis,guava,caffeine,jCache,ehCache等等),并提供一致的对外接口;
包括CacheManager和Cache两个接口,Cache接口包含缓存的各种操作,CacheManager接口则负责管理Cache;
CacheManager会持有多个Cache实例的引用,根据name区分;
Cache接口包含一些简单的缓存操作,功能没有redisTemplate强大;
可使用代码调用,也可使用注解,使用注解更为方便;
代码:cacheManager.getCache(“test”).put(“key”, “value”);
注解:(转)注解示例
2.spring cache结构
3.spring cache解析
3.1.cache和cacheManager接口
cache接口包含缓存的各种操作,CacheManager接口持有cache接口实例,并负责管理Cache;
public interface Cache {
//**获取cache的名称
String getName();
//**获取底层真正使用的缓存(concurrentMap,redis)
Object getNativeCache();
//**根据key获取value,ValueWrapper是一个函数式接口,可自定义实现定义value的转换操作
ValueWrapper get(Object key);
//**根据key获取value,并把value转换为type类型
T get(Object key, @Nullable Class type);
//**根据key获取value,Callable任务计算value
T get(Object key, Callable valueLoader);
//**保存键值对
void put(Object key, @Nullable Object value);
//**如果键值对不存在则保存并返回null,存在则返回已存在的value
default ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
ValueWrapper existingValue = get(key);
if (existingValue == null) {
put(key, value);
}
return existingValue;
}
//**删除键值对
void evict(Object key);
//**删除键值对,并返回键值对是否存在
default boolean evictIfPresent(Object key) {
evict(key);
return false;
}
//**删除所有键值对
void clear();
//**删除所有键值对,并返回之前是否存在键值对
default boolean invalidate() {
clear();
return false;
}
//**缓存value的包装器
@FunctionalInterface
interface ValueWrapper {
//**标记返回值可为空,大部分ide可支持编译期检查
@Nullable
Object get();
}
}
public interface CacheManager {
//**根据name获取CacheManager管理的Cache
Cache getCache(String name);
//**获取CacheManager管理的所有Cache的名称
Collection getCacheNames();
}
3.2.AbstractValueAdaptingCache
保存的value为null时,如果allowNullValues=true,则保存NullValue,如果allowNullValues=false,则抛出异常。默认为true;
读取的value为NullValue时,返回null,不受allowNullValues影响;
lookup方法直接从底层存储获取value,不会进行任何处理和转换,其它方法会对value进行一些处理;
//**抽象类,对value进行一行处理
public abstract class AbstractValueAdaptingCache implements Cache {
//**是否允许空值
private final boolean allowNullValues;
//**获取value,然后转换为ValueWrapper
public ValueWrapper get(Object key) {
Object value = lookup(key);
return toValueWrapper(value);
}
//**获取value,并强制转换为type类型
public T get(Object key, @Nullable Class 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;
}
//**获取value,不进行任务其它处理和转换
protected abstract Object lookup(Object key);
//**获取value时进行空值处理
protected Object fromStoreValue(@Nullable Object storeValue) {
if (this.allowNullValues && storeValue == NullValue.INSTANCE) {
return null;
}
return storeValue;
}
//**保存value时进行空值处理
protected Object toStoreValue(@Nullable Object userValue) {
if (userValue == null) {
if (this.allowNullValues) {
return NullValue.INSTANCE;
}
throw new IllegalArgumentException(
"Cache '" + getName() + "' is configured to not allow null values but null was provided");
}
return userValue;
}
//**把value转换为SimpleValueWrapper
protected Cache.ValueWrapper toValueWrapper(@Nullable Object storeValue) {
return (storeValue != null ? new SimpleValueWrapper(fromStoreValue(storeValue)) : null);
}
}
3.3.ConcurrentMapCache和ConcurrentMapCacheManager
ConcurrentMapCache使用ConcurrentMap作为缓存的存储;
ConcurrentMapCacheManager使用ConcurrentMap保存name和ConcurrentMapCache的键值对;
ConcurrentMapCache是AbstractValueAdaptingCache的子类,继承了AbstractValueAdaptingCache对空值的处理方式;
如果SerializationDelegate!=null,则会对value进行序列化,为null则直接保存value对象。默认为null;
SerializationDelegate使用了delegate委派模式:
类B和类A是两个互相没有任何关系的类,但是B有和A一样的方法和属性;
B中的方法/属性直接调用A中同名的方法和属性;
delegate委派和proxy代理的区别:
委派:类B和类A没有任何关系;
代理:类B和类A需要实现同一个接口;
public class ConcurrentMapCache extends AbstractValueAdaptingCache {
//*cache的name
private final String name;
//**cache底层使用的存储
private final ConcurrentMap store;
//**序列化工具(delegate委派模式)
private final SerializationDelegate serialization;
//**获取value,不进行任务其它处理和转换
protected Object lookup(Object key) {
return this.store.get(key);
}
//**获取value,有则返回,没有则调用传入的Callable获取值,并保存到缓存中
public T get(Object key, Callable valueLoader) {
return (T) fromStoreValue(this.store.computeIfAbsent(key, k -> {
try {
return toStoreValue(valueLoader.call());
}
catch (Throwable ex) {
throw new ValueRetrievalException(key, valueLoader, ex);
}
}));
}
//**保存value
public void put(Object key, @Nullable Object value) {
this.store.put(key, toStoreValue(value));
}
//**键值对不存在则保存,并把当前缓存中的value转换SimpleValueWrapper为后返回
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
Object existing = this.store.putIfAbsent(key, toStoreValue(value));
return toValueWrapper(existing);
}
//**删除键值对
public void evict(Object key) {
this.store.remove(key);
}
//**删除键值对,并返回键值对是否存在
public boolean evictIfPresent(Object key) {
return (this.store.remove(key) != null);
}
//**删除所有键值对
public void clear() {
this.store.clear();
}
//**删除键值对,并返回是否存在键值对
public boolean invalidate() {
boolean notEmpty = !this.store.isEmpty();
this.store.clear();
return notEmpty;
}
//**保存value时进行空值处理,对并对value进行序列化
protected Object toStoreValue(@Nullable Object userValue) {
Object storeValue = super.toStoreValue(userValue);
if (this.serialization != null) {
try {
return serializeValue(this.serialization, storeValue);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Failed to serialize cache value '" + userValue +
"'. Does it implement Serializable?", ex);
}
}
else {
return storeValue;
}
}
//**调用SerializationDelegate对value进行序列化
private Object serializeValue(SerializationDelegate serialization, Object storeValue) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
serialization.serialize(storeValue, out);
return out.toByteArray();
}
finally {
out.close();
}
}
//**获取value时进行空值处理,对并对value进行反序列化
protected Object fromStoreValue(@Nullable Object storeValue) {
if (storeValue != null && this.serialization != null) {
try {
return super.fromStoreValue(deserializeValue(this.serialization, storeValue));
}
catch (Throwable ex) {
throw new IllegalArgumentException("Failed to deserialize cache value '" + storeValue + "'", ex);
}
}
else {
return super.fromStoreValue(storeValue);
}
}
//**调用SerializationDelegate对value进行反序列化
private Object deserializeValue(SerializationDelegate serialization, Object storeValue) throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream((byte[]) storeValue);
try {
return serialization.deserialize(in);
}
finally {
in.close();
}
}
}
Aware接口,一个标记,标记在spring容器初始化时需要获取上下文中当前的一些运行环境,如BeanFactoryAware,ApplicationContextAware等;
BeanClassLoaderAware,获取当前的ClassLoader;
如果初始化时创建了缓存,则后续只能使用初始化的缓存,不能创建新缓存;
如果初始化时没有创建缓存,则后续使用时动态的创建新缓存;
保存value时,如果storeByValue=false,会对value进行序列化,为true则直接保存value,默认为false;
public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
//**使用ConcurrentMap保存和管理ConcurrentMapCache
private final ConcurrentMap cacheMap = new ConcurrentHashMap<>(16);
//**是否允许动态的创建ConcurrentMapCache
private boolean dynamic = true;
//**是否允许空值
private boolean allowNullValues = true;
//**保存value时是否允许对value进行序列化
private boolean storeByValue = false;
//**序列化器
private SerializationDelegate serialization;
//**默认构造方法,不创建任何缓存,当获取缓存时,如果不存在,则创建新的缓存
public ConcurrentMapCacheManager() {
}
//**根据传入的cache name创建多个ConcurrentMapCache,后续则不能在创建新的缓存
public void setCacheNames(@Nullable Collection cacheNames) {
if (cacheNames != null) {
for (String name : cacheNames) {
this.cacheMap.put(name, createConcurrentMapCache(name));
}
this.dynamic = false;
}
else {
this.dynamic = true;
}
}
//**设置是否允许空值,对所有缓存有效
public void setAllowNullValues(boolean allowNullValues) {
if (allowNullValues != this.allowNullValues) {
this.allowNullValues = allowNullValues;
// Need to recreate all Cache instances with the new null-value configuration...
recreateCaches();
}
}
//**设置是否允许对value进行序列化,对所有缓存有效
public void setStoreByValue(boolean storeByValue) {
if (storeByValue != this.storeByValue) {
this.storeByValue = storeByValue;
// Need to recreate all Cache instances with the new store-by-value configuration...
recreateCaches();
}
}
//**继承自BeanClassLoaderAware,根据注入的ClassLoader创建序列化器(使用java序列化和反序列化)
public void setBeanClassLoader(ClassLoader classLoader) {
this.serialization = new SerializationDelegate(classLoader);
// Need to recreate all Cache instances with new ClassLoader in store-by-value mode...
if (isStoreByValue()) {
recreateCaches();
}
}
//**获取所有的cache name,返回一个不可变的set
public Collection getCacheNames() {
return Collections.unmodifiableSet(this.cacheMap.keySet());
}
//**根据name获取cache,如果cache不存在且dynamic=true,则根据name创建一个cache,并保存到cacheMap中(线程安全的)
public Cache getCache(String name) {
Cache cache = this.cacheMap.get(name);
if (cache == null && this.dynamic) {
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
cache = createConcurrentMapCache(name);
this.cacheMap.put(name, cache);
}
}
}
return cache;
}
//**根据当前的name,重新创建新的cache
private void recreateCaches() {
for (Map.Entry entry : this.cacheMap.entrySet()) {
entry.setValue(createConcurrentMapCache(entry.getKey()));
}
}
//**根据name创建新的ConcurrentMapCache
protected Cache createConcurrentMapCache(String name) {
SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),
isAllowNullValues(), actualSerialization);
}
}
3.4.TransactionAwareCacheDecorator和TransactionAwareCacheManagerProxy
TransactionAwareCacheDecorator使用了decorator装饰器模式;
TransactionAwareCacheManagerProxy使用了proxy代理模式;
装饰器模式和代理模式的区别:
装饰器:关注于在一个对象上动态的添加方法;通常在装饰器的构造方法中,需要传入装饰的类的实例,实例化后通常不允许修改装饰的类;
代理:关注于控制对对象的访问;通常由代理类自己创建代理类的实例,调用时由代理类判断应该调用哪个实例的方法;
本身并没有缓存功能,作用是扩展普通的cache和cacheManager,使其支持事务;
public class TransactionAwareCacheDecorator implements Cache {
//**装饰的类,实例化后不允许修改
private final Cache targetCache;
//**保存value时,判断是否存在事务,存在事务则在事务提交之后保存value
public void put(final Object key, @Nullable final Object value) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
}
});
}
else {
this.targetCache.put(key, value);
}
}
//**删除键值对时,判断是否存在事务,存在事务则在事务提交之后删除键值对
public void evict(final Object key) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.evict(key);
}
});
}
else {
this.targetCache.evict(key);
}
}
//**清除所有键值对时,判断是否存在事务,存在事务则在事务提交之后清除所有键值对
public void clear() {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
targetCache.clear();
}
});
}
else {
this.targetCache.clear();
}
}
}
InitializingBean接口,spring容器启用时,会调用afterPropertiesSet方法进行一些初始化,同类型还有 @PostConstruct;
public class TransactionAwareCacheManagerProxy implements CacheManager, InitializingBean {
//**代理的cacheManager,后续可通用set方法修改代理的cacheManager
private CacheManager targetCacheManager;
//**根据name获取cache时,对cache进行装饰,以支持事务
public Cache getCache(String name) {
Assert.state(this.targetCacheManager != null, "No target CacheManager set");
Cache targetCache = this.targetCacheManager.getCache(name);
return (targetCache != null ? new TransactionAwareCacheDecorator(targetCache) : null);
}
}
3.5.AbstractCacheManager和AbstractTransactionSupportingCacheManager
public abstract class AbstractCacheManager implements CacheManager, InitializingBean {
//**使用ConcurrentMap保存和管理ConcurrentMapCache
private final ConcurrentMap cacheMap = new ConcurrentHashMap<>(16);
//**使用Set保存所有的cache name
private volatile Set cacheNames = Collections.emptySet();
//**创建时初始化缓存
@Override
public void afterPropertiesSet() {
initializeCaches();
}
//**初始化缓存,并把缓存的name保存到cacheNames中
public void initializeCaches() {
Collection extends Cache> caches = loadCaches();
synchronized (this.cacheMap) {
this.cacheNames = Collections.emptySet();
this.cacheMap.clear();
Set cacheNames = new LinkedHashSet<>(caches.size());
for (Cache cache : caches) {
String name = cache.getName();
this.cacheMap.put(name, decorateCache(cache));
cacheNames.add(name);
}
this.cacheNames = Collections.unmodifiableSet(cacheNames);
}
}
//**加载cache
protected abstract Collection extends Cache> loadCaches();
//**根据名称获取cache
public Cache getCache(String name) {
//**如果cache存在则直接返回
Cache cache = this.cacheMap.get(name);
if (cache != null) {
return cache;
}
//**不存在,调用getMissingCache获取cache
Cache missingCache = getMissingCache(name);
if (missingCache != null) {
//**如果getMissingCache返回的cache不存在,则对cache进行装饰,并保存
synchronized (this.cacheMap) {
cache = this.cacheMap.get(name);
if (cache == null) {
cache = decorateCache(missingCache);
this.cacheMap.put(name, cache);
updateCacheNames(name);
}
}
}
return cache;
}
//**添加缓存
protected final void addCache(Cache cache) {
String name = cache.getName();
synchronized (this.cacheMap) {
if (this.cacheMap.put(name, decorateCache(cache)) == null) {
updateCacheNames(name);
}
}
}
//**对cache进行装饰
protected Cache decorateCache(Cache cache) {
return cache;
}
//**如果name对应的cache不存在时,如何获取cache
protected Cache getMissingCache(String name) {
return null;
}
}
transactionAware=true,则使用TransactionAwareCacheDecorator装饰cache,以支持事务,如果为false,则不会装饰cache。默认false;
public abstract class AbstractTransactionSupportingCacheManager extends AbstractCacheManager {
//**是否支持事务
private boolean transactionAware = false;
//**如果需要支持事务,则使用TransactionAwareCacheDecorator装饰cache,以支持事务
protected Cache decorateCache(Cache cache) {
return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache) : cache);
}
}