论坛首页 Java企业应用论坛

抄袭ibatis缓存设计。自实现缓存设计

浏览 8587 次
精华帖 (0) :: 良好帖 (6) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-07-31   最后修改:2012-07-31
1.较为简单的缓存机制,不支持分布式缓存。
2.目前只实现了memory形式。如有扩展,请自实现fifo,lru等形式。
3.为了缓存机制过于复杂,暂不支持配置文件形式。以后会用第三方组件代替,没必要在此处下太大功夫。
4.增加了factory生成相应的cachemodel。保证单例。
5.使用方式:
5.1factory通过加载指定的缓存机制生产cachemodel(缓存包装类),每种cachecontrol对应一个cachemodel(单例)。
5.2通过操作cachemodel(内部包含了cachecontrol接口,解耦)来进行实际的动作。

核心code.

package com.common.utils.cacheUtils.myCache;

import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * 缓存模式包装类,公用的设计均写在此处。(日志,控制时间等等。) <br>
 * 
 * @author yzx
 * @see
 * @since
 */
public class CacheModel {

    private static Logger     logger              = Logger.getLogger(CacheModel.class);
    private CacheControl      cacheControl;
    private static final int  MAX_OBJECT_LOG_SIZE = 100;
    private static final long NO_FLUSH_INTERVAL   = -99999;
    private String            id;
    private boolean           readOnly;
    private boolean           serialize;
    private long              lastFlush;
    private long              flushInterval;
    private long              flushIntervalSeconds;

    private CacheModel() {

    }

    /**
     * 缓存模式初始化
     * 
     * @param controllerClassName
     */
    protected CacheModel(String controllerClassName) {
        try {
            this.flushInterval = NO_FLUSH_INTERVAL;
            this.flushIntervalSeconds = NO_FLUSH_INTERVAL;
            this.lastFlush = System.currentTimeMillis();
            cacheControl = (CacheControl) Class.forName(controllerClassName).newInstance();
        } catch (Exception e) {
            logger.error("缓存控制器包装类初始化失败!" + e.getMessage());
            throw new RuntimeException("缓存控制器包装类初始化失败!");
        }

    }

    public void configure(Properties props) {
        cacheControl.configure(props);
    }

    /**
     * Clears the cache
     */
    public void flush() {
        synchronized (this) {
            cacheControl.flush(this);
            lastFlush = System.currentTimeMillis();
        }
    }

    public Object getObject(Object key) {
        Object value = null;
        // 暂不用,若使用,需要同步
        // if (flushInterval != NO_FLUSH_INTERVAL && System.currentTimeMillis() - lastFlush > flushInterval) {
        // flush();
        // }
        value = cacheControl.getObject(this, key);
        return value;

    }

    public void putObject(Object key, Object value) {
        synchronized (this) {
            cacheControl.putObject(this, key, value);
        }
    }

    public Object removeObject(Object key) {
        synchronized (this) {
            return cacheControl.removeObject(this, key);
        }

    }

    public static Logger getLogger() {
        return logger;
    }

    public static void setLogger(Logger logger) {
        CacheModel.logger = logger;
    }

    // public CacheControl getCacheControl() {
    // return cacheControl;
    // }
    //
    // public void setCacheControl(CacheControl cacheControl) {
    // this.cacheControl = cacheControl;
    // }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;
    }

    public boolean isSerialize() {
        return serialize;
    }

    public void setSerialize(boolean serialize) {
        this.serialize = serialize;
    }

    public long getLastFlush() {
        return lastFlush;
    }

    public void setLastFlush(long lastFlush) {
        this.lastFlush = lastFlush;
    }

    public long getFlushInterval() {
        return flushInterval;
    }

    public void setFlushInterval(long flushInterval) {
        this.flushInterval = flushInterval;
    }

    public long getFlushIntervalSeconds() {
        return flushIntervalSeconds;
    }

    public void setFlushIntervalSeconds(long flushIntervalSeconds) {
        this.flushIntervalSeconds = flushIntervalSeconds;
    }

    public static int getMaxObjectLogSize() {
        return MAX_OBJECT_LOG_SIZE;
    }

    public static long getNoFlushInterval() {
        return NO_FLUSH_INTERVAL;
    }

}



package com.common.utils.cacheUtils.myCache;

import java.util.Properties;

/**
 * Description:缓存自实现接口 <br>
 * 
 * @author yzx
 * @see
 * @since
 */
public interface CacheControl {

    /**
     * 清空缓存
     * 
     * @param cacheModel
     */
    public void flush(CacheModel cacheModel);

    /**
     * 获取缓存值
     * 
     * @param cacheModel
     * @param key
     * @return
     */
    public Object getObject(CacheModel cacheModel, Object key);

    /**
     * 移除某个缓存值
     * 
     * @param cacheModel
     * @param key
     * @return
     */
    public Object removeObject(CacheModel cacheModel, Object key);

    /**
     * 更新缓存
     * 
     * @param cacheModel
     * @param key
     * @param value
     */
    public void putObject(CacheModel cacheModel, Object key, Object value);

    /**
     * 为配置文件做扩展用,暂不用(不想在此处做的太复杂。将来会考虑用第三方组件)
     * 
     * @param props
     */
    @Deprecated
    public void configure(Properties props);
}




具体的一个实现

package com.common.utils.cacheUtils.myCache.memory;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import com.common.utils.cacheUtils.myCache.CacheControl;
import com.common.utils.cacheUtils.myCache.CacheModel;

/**
 * 内存缓存控制策略,根据内存占用情况来做缓存
 * Description: <br>
 * 
 * @author yzx
 * @see
 * @since
 */
@SuppressWarnings("unchecked")
public class MemoryCacheController implements CacheControl {

    // private final String cacheLevel = "WEAK";
    // private final String cacheLevel = "SOFT";
    private final String cacheLevel = "STRONG";
    private Map          cache      = new ConcurrentHashMap();

    @Override
    public void configure(Properties props) {

    }

    @Override
    public void flush(CacheModel cacheModel) {
        cache.clear();

    }

    @Override
    public Object getObject(CacheModel cacheModel, Object key) {
        Object value = null;
        Object ref = cache.get(key);
        if (ref != null) {
            if (ref instanceof StrongReference) {
                value = ((StrongReference) ref).get();
            } else if (ref instanceof SoftReference) {
                value = ((SoftReference) ref).get();
            } else if (ref instanceof WeakReference) {
                value = ((WeakReference) ref).get();
            }
        }
        return value;
    }

    @Override
    public void putObject(CacheModel cacheModel, Object key, Object value) {
        Object reference = null;
        if (cacheLevel.equals("WEAK")) {
            reference = new WeakReference(value);
        } else if (cacheLevel.equals("SOFT")) {
            reference = new SoftReference(value);
        } else if (cacheLevel.equals("STRONG")) {
            reference = new StrongReference(value);
        }
        cache.put(key, reference);
    }

    @Override
    public Object removeObject(CacheModel cacheModel, Object key) {
        Object value = null;
        Object ref = cache.remove(key);
        if (ref != null) {
            if (ref instanceof StrongReference) {
                value = ((StrongReference) ref).get();
            } else if (ref instanceof SoftReference) {
                value = ((SoftReference) ref).get();
            } else if (ref instanceof WeakReference) {
                value = ((WeakReference) ref).get();
            }
        }
        return value;
    }

    /**
     * 强引用,不被垃圾回收
     * Description: <br>
     * 
     * @author yzx
     * @see
     * @since
     */
    private static class StrongReference {

        private Object object;

        public StrongReference(Object object) {
            this.object = object;
        }

        public Object get() {
            return object;
        }
    }

}


简单类图
[img]
b.jpg
[/img]
  • 大小: 49.3 KB
   发表时间:2012-08-01  
欢迎批评。
0 请登录后投票
   发表时间:2012-08-01  
果然是完全抄袭ibatis2.3的Memory Cache实现源码,
0 请登录后投票
   发表时间:2012-08-02  
缓存不应该用在Dao
0 请登录后投票
   发表时间:2012-08-02  
weng 写道
缓存不应该用在Dao

这个不一定,还是要看场景。
如果传入参数比较稳定,结果集比较小的场景,可以考虑使用ibatis的缓存,简洁方便。反之,如果sql传入的参数变化很多,或结果集数据量非常庞大,不适合使用ibatis缓存,可以考虑使用其他分布式缓存(memcache等)替代。
0 请登录后投票
   发表时间:2012-08-02  
我想问下,这个分布式的缓存是指把数据放在硬盘么,
在我学习的时候,有时候自己写个静态到map作为map,那么是放在内存的,
而这个分布式的缓存是否是放在硬盘,或者是别的电脑上的内存,又或者。。。

我还是查查google吧
0 请登录后投票
   发表时间:2012-08-02  
learnworld 写道
果然是完全抄袭ibatis2.3的Memory Cache实现源码,

基本是的,重复造轮子感觉也不是那么回事。只是精简化了并且把xml改成factory。
0 请登录后投票
   发表时间:2012-08-02  
endual 写道
我想问下,这个分布式的缓存是指把数据放在硬盘么,
在我学习的时候,有时候自己写个静态到map作为map,那么是放在内存的,
而这个分布式的缓存是否是放在硬盘,或者是别的电脑上的内存,又或者。。。

我还是查查google吧



或许你也可以baidu。。
0 请登录后投票
   发表时间:2012-08-24  

有没有考虑过:

  1. cache数据的全部刷新,即可能需要一个事务内完成连续的写入
  2. 读数据时,是否有线程同时正在flush,还没完成写入
  3. 读写锁
0 请登录后投票
   发表时间:2012-09-04  
linjinxiao 写道

有没有考虑过:

  1. cache数据的全部刷新,即可能需要一个事务内完成连续的写入
  2. 读数据时,是否有线程同时正在flush,还没完成写入
  3. 读写锁

这就是为什么里面会有同步的原因。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics