预备知识:
缓存整体结构图:

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;
}
}
刷新缓存的方法:
要做的核心工作有如下三项:
- 清理原来的缓存
- 重新刷数据
- 重新建立索引
清理缓存:
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、扩展刷新缓存的方式

被折叠的 条评论
为什么被折叠?



