一、概述

现状:目前缓存框架底层使用redis,但是进行了统一包装,相当于对外一个新缓存框架,提供了redis基础功能

问题:缓存混乱乱,由程序员自己set,get。清理不彻底。线上出问题。

需求:项目需要使用spring cache统一对service进行缓存处理。团队统一的缓存管理,以及同外部一致的缓存策略方案

1.1、实现自定义缓存方案

  参看缓存实现图:006-spring cache-缓存实现-01-SimpleCacheConfiguration、RedisCacheConfiguration

  参看redis 实现架构

    009-spring cache-自己定制缓存接入。CacheManager和Cache

  SpringCache本质上是一个对缓存使用的抽象,将存储的具体实现方案从缓存执行动作及流程中提取出来。缓存流程中面向的两个抽象接口是CacheManager、Cache。其中Cache提供了缓存操作的读取/写入/移除等方法,本着面向抽象编程的原则,内部将缓存对象统一封装成ValueWrapper。Cache接口代码如下:

public interface Cache {    
    String getName();  //缓存的名字    
    Object getNativeCache(); //得到底层使用的缓存,如Ehcache    
    ValueWrapper get(Object key); //根据key得到一个ValueWrapper,然后调用其get方法获取值    
    <T> T get(Object key, Class<T> type);//根据key,和value的类型直接获取value    
    void put(Object key, Object value);//往缓存放数据    
    void evict(Object key);//从缓存中移除key对应的缓存    
    void clear(); //清空缓存    
    
    interface ValueWrapper { //缓存值的Wrapper    
        Object get(); //得到真实的value    
    }    
}

由于在应用中可能定义多个Cache,因此提供了CacheManager抽象,用于缓存的管理,接口代码如下:

public interface CacheManager {    
    Cache getCache(String name); //根据Cache名字获取Cache     
    Collection<String> getCacheNames(); //得到所有Cache的名字    
}

  任何实现了这两个接口的缓存方案都可以直接配置进SpringCache使用。其自带的SimpleCacheManager、ConcurrentMapCache是如此;使用ehcache作为存储实现的EhCacheCacheManager、EhCacheCache也是如此。可以自己实现CacheManager与Cache并将其集成进来。

二、自定义缓存实现

2.1、自定义缓存实现-基础版本【需要自己手动写缓存空间】

1、Cache接口,增删改差

  为了方便展示,自定义缓存实现方案只实现最简单的功能,cache内部使用ConcurrentHashMap做为存储方案,使用默认实现SimpleValueWrapper,MyCache代码如下:

package com.aaa.test.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.context.annotation.Configuration;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

@Configuration
public class MyCache implements Cache {
    final static Logger logger = LoggerFactory.getLogger(MyCache.class);

    String name;
    Map<Object, Object> store = new ConcurrentHashMap<Object, Object>();

    public MyCache() {
    }

    public MyCache(String name) {
        this.name = name;
    }

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


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


    @Override
    public ValueWrapper get(Object key) {
        ValueWrapper result = null;
        Object thevalue = store.get(key);
        if(thevalue!=null) {
            logger.info("["+name+"]got cache, key:"+key);
            result = new SimpleValueWrapper(thevalue);
        }else{
            logger.info("["+name+"]missing cache, key:"+key);
        }
        return result;
    }


    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(Object key, Class<T> type) {
        ValueWrapper vw = get(key);
        if(vw==null){
            return null;
        }
        return (T)vw.get();
    }


    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        ValueWrapper vw = get(key);
        if(vw==null){
            return null;
        }
        return (T)vw.get();
    }


    @Override
    public void put(Object key, Object value) {
        store.put(key, value);
    }


    @Override
    public Cache.ValueWrapper putIfAbsent(Object key, Object value) {
        Object existing = this.store.putIfAbsent(key, value);
        return (existing != null ? new SimpleValueWrapper(existing) : null);
    }


    @Override
    public void evict(Object key) {
        store.remove(key);
    }


    @Override
    public void clear() {
        store.clear();
    }
}
View Code

相关文章: