一个简单的缓存实现方案【附源码】

动机

在研发中进场会碰到一些更改频率很低但是需要频繁访问的对象,比如:数据字典。这是缓存是最好的解决防范,Spring提供了一个通用的缓存框架Ehcache,那我为什么还要自己写一个呢?

  1. Spring ehcahe是一个通用的方案,他可以使用内存也可以使用磁盘,这是一个很好的优点,它拜托了内存大小的限制,但是会进行序列化导致性能降低。
  2. 如果一个对象集合同时需要list的形式存储已获得整体又需要以HashMap的形式组织以方便查询 Ehcache会缓存两次,所以我们需要一个缓存依赖关系。
    鉴于以上原因我们设计了一个简单实用的缓存方案。

设计思想

做这个缓存方案主要目的是减少内存的消耗、增强缓存内容的访问效率。

  1. 设计一个接口 ICachedObject<T> 它有一个是缓存失效的方法。
  2. 设计一个抽象类AbstractCachedObject<T> 它维护一个缓存依赖关系和当前缓存状态。
  3. CachedObject<T>类是一个缓存的最简单的实现,它需要一个生产者Supplier<T> 在缓存失效时刷新数据,缓存对象在初始化时总是失效的。另外缓存在初始化时可以 设置其依赖的其它缓存对象,一个缓存可以依赖多个其它缓存对象。
  4. CachedMap<K,T>是按照键值缓存的对象,它和CachedObject<Map<K,T>>是不一样的,后者作为一个对象整体缓存,前者是按照key分别缓存,每个key的状态是不一样的。CachedMap需要个生产者Function<K, T>。
  5. DerivativeCachedMap

使用

// 定义缓存对象 ,需要提供刷新函数 this::reloadUserInfo
private CachedObject<List<ExtSysUserInfo>> allUserInfoCache =
        new CachedObject<>( this::reloadUserInfo,
            // 缓存数据的有效期
            CodeRepositoryCache.CACHE_FRESH_PERIOD_MINITES);
// 缓存刷新函数,一般也是访问数据库获取真正对象的函数            
protected List<ExtSysUserInfo> reloadUserInfo() {
        try(Connection conn = getDatabaseConnection() ) {
            ..............................
            return allUserInfo;
        }catch (SQLException |IOException  e){
            logger.error(e.getLocalizedMessage());
            return null;
        }
    }
// 定义一个派生缓存
private CachedObject<Map<String,ExtSysUserInfo>> codeToUserMapCache=
        // 刷新函数
        new CachedObject<>( ()-> {
                // 从其它缓存获取数据
                List<ExtSysUserInfo> userInfos = allUserInfoCache.getCachedTarget();
                if(userInfos==null){
                    return null;
                }
                Map<String, ExtSysUserInfo> userCodeMap = new HashMap<>(userInfos.size()+1);
                for(ExtSysUserInfo userInfo : userInfos ){
                    userCodeMap.put(userInfo.getUserCode(), userInfo);
                }
                return userCodeMap;
            },
            // 依赖的缓存,可以是多个;派生缓存没有有效期,它随依赖的缓存失效而失效
            allUserInfoCache);

// 使用缓存,派生缓存的使用方法一样,CachedMap的使用参见源码 
public List<ExtSysUserInfo> listAllUserInfo() {
        return allUserInfoCache.getCachedTarget();
    }

源码

ICachedObject.java AbstractCachedObject.java CachedObject.java CachedMap.java DerivativeCachedMap.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值