一种cache体系的设计

预备知识:

《JAVA与模式》之模板方法模式

回调方法、模板方法模式、钩子(hook)区分

理解回调机制-java

缓存整体结构图:

CacheFactory是个单实例,管理所有缓存,可以把CacheFactory看成最大容器。里面防着一个个cache.

public class CacheFactory {
    /**  存放缓存实例  */
    private Map _cacheMap;
	//添加缓存
	public void addCache(Cache cache) throws CacheException {

        synchronized(_cacheMap){
            if(_cacheMap.containsKey(cache.getCacheID())) {
                throw new Exception;
            }
            _cacheMap.put(cache.getCacheID(), cache);
        }
    }
}

核心类的体系: 

如何创建一个cahce对象呢?

		//数据字典
		CachedObjectKeyDef[] dicKeys = {new Dictionary_Key(true)};
		UpdatableCache dicCache = new UpdatableCache(Constants.CACHE_DIC, dicKeys, false, new Dictionary_Refresh());
		CacheFactory.getInstance().addCache(dicCache);

cache内部构造方法:

	public UpdatableCache(String cacheId,CachedObjectKeyDef[] keydefs,Boolean isCopy,RefreshCallBack refreshCallBack) throws CacheException  {
		   super(cacheId, keydefs, isCopy, refreshCallBack);
	}

 构造一个一类cache的三个关键步骤:

刷数据库数据到内存,

建立索引体系(2层索引体系);

设置缓存名称 cache id.

	public GenericCache(String cacheId,CachedObjectKeyDef[] keydefs,Boolean isCopy,RefreshCallBack refreshCallBack) throws CacheException  {
		callBackExecutor.setRefreshCallBack(refreshCallBack); 
		List list = callBackExecutor.executeRefreshCallBack();

		this.setCacheID(cacheId);
		
		this.isCopy = isCopy;
		if(isCopy==false){
			this.cache = list;
		}
		if(list!=null)Collections.unmodifiableList(this.cache);
		//CachedObjectKeyDef[] keydefs 
		this.keydefs = new CachedObjectKeyDef[keydefs.length];
		System.arraycopy(keydefs, 0, this.keydefs , 0, keydefs.length);
		createIndexAndSort(list,this.keydefs);
	}

createIndexAndSort的方法:

	/**
	 * 创建索引
	 * @param list
	 * @param keys
	 */
	public  void createIndexAndSort(List list,CachedObjectKeyDef[] keydefs){
		//初始化索引的索引
		int len=keydefs.length;
		for(int i=0;i<len; i++){
			Map map = new HashMap();
            //第一层索引
			index.put((Class<CachedObjectKeyDef>) keydefs[i].getClass(), map);
		}

		//分别处理各个索引  为每个具体对象 建立*个索引
		for(Iterator it = list.iterator();it.hasNext();){
			Object obj = it.next();
			for(int i=0; i< len; i++){
                //构建第2层索引
				addObject2Index(index.get(keydefs[i].getClass()),keydefs[i],obj);
		    }
		}
		sort( keydefs);
	}

这里index 是generic的一个属性:private Map<Class<CachedObjectKeyDef>,Map> index = new HashMap();

	/**
	 * 为对象建立索引(第2层索引)
	 * @param m
	 * @param key
	 * @param value
	 */
	private void addObject2Index(Map m,CachedObjectKeyDef keydef,Object value){
                ......

            if (keydef.isUnique())
            {
                Object objectKey = keydef.createKey(value);
                if (objectKey != null)
                	 m.put(objectKey, value);
            }else{
              //把对象放入一个集合
            }
           ......

            }

 ps:根据key查询一个对象:

	public Object getObjectByKey(CachedObjectKeyDef keydef,Object key) throws CacheException{
		Object m = index.get(keydef.getClass());
			Map map = (Map)m;
			Object obj = map.get(key);
			return obj;

	}

刷数据库数据到内存,

/**
 * 缓存刷新的回调接口
 * 通过该接口缓存可以获得到要缓存的数据集合
 *
 */
public interface RefreshCallBack {
	   
	  /**
	    * @return
	    */
       public List setSourceList();
}

取得数据 由于各个类不相同,我们抽象出统一的接口,需要的时候,由具体类刷新数据。 

public class BasBillInfo_Refresh implements RefreshCallBack{
/**
 * 告诉缓存系统 如何取得对象数据
 */	
	@Override
	@SuppressWarnings("unchecked")
	public List setSourceList() { 
		//因为是注解的bean,所以默认bean的ID是class名,首字母小写dictionaryDaoImpl
		BaseDao billDesignerDao = (BaseDao)Tool.getBean("baseDao");	
		List<EBasBillInfo> result = new ArrayList();
		try {
			//因为是多区划,所以去掉一些单一区划条件
			result = billDesignerDao.findByHql("from EBasBillInfo order by billcode asc");

			System.out.println("BasBillInfo_Refresh___>>>> "+result.size());
		} catch (Exception e) {
			e.printStackTrace();
		}		 
		return result;
	}

}

刷新缓存的方法:

要做的核心工作有如下三项:

  1. 清理原来的缓存
  2. 重新刷数据
  3. 重新建立索引

清理缓存:

	public void clear(){
		if(this.cache!=null)this.cache.clear();  //清理数据
		if(this.index!=null)this.index.clear();  //清理索引
		if(this.sortCache!=null)this.sortCache.clear();  //清理排序
	}

刷新缓存:

	/**
	 * 刷新缓存
	 */
	@Override
	public synchronized void refresh(){
		List list = callBackExecutor.executeRefreshCallBack();

		this.clear();

		if(isCopy==false){
			this.cache = list;
		}
		createIndexAndSort(list,this.keydefs);
	}
	 

和spring集成的思路:

1、扩展索引的建立
2、扩展刷新数据方式
3、扩展刷新缓存的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值