(1)首先是Cache接口定义:
package org.apache.ibatis.cache; import java.util.concurrent.locks.ReadWriteLock; public interface Cache { String getId(); int getSize(); void putObject(Object key, Object value); Object getObject(Object key); Object removeObject(Object key); void clear(); ReadWriteLock getReadWriteLock(); }
package cn.lsoft.undoner.dao.cache; import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.commons.codec.digest.DigestUtils; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.lsoft.undoner.util.SerializeUtil; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /* * 使用第三方缓存服务器,处理二级缓存 */ public class RedisCache implements Cache { private static Logger logger = LoggerFactory.getLogger(RedisCache.class); /** The ReadWriteLock. */ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private String id; private JedisPool jedisPool; private static final int DB_INDEX = 1; private final String COMMON_CACHE_KEY = "COM:"; private static final String UTF8 = "utf-8"; private ApplicationContext context; /** * 按照一定规则标识key */ private String getKey(Object key) { StringBuilder accum = new StringBuilder(); accum.append(COMMON_CACHE_KEY); accum.append(this.id).append(":"); accum.append(DigestUtils.md5Hex(String.valueOf(key))); return accum.toString(); } /** * redis key规则前缀 */ private String getKeys() { return COMMON_CACHE_KEY + this.id + ":*"; } public RedisCache() { } public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("必须传入ID"); } context = new ClassPathXmlApplicationContext("/spring/spring-db-redis-context.xml"); JedisPoolConfig jedisPoolConfig = (JedisPoolConfig) context.getBean("poolConfig"); jedisPool = new JedisPool(jedisPoolConfig, "23.45.6.7", 6379); logger.debug(">>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id); this.id = id; } @Override public String getId() { return this.id; } @Override public int getSize() { Jedis jedis = null; int result = 0; boolean borrowOrOprSuccess = true; try { jedis = jedisPool.getResource(); jedis.select(DB_INDEX); Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF8)); if (null != keys && !keys.isEmpty()) { result = keys.size(); } logger.debug(this.id + "---->>>>总缓存数:" + result); } catch (Exception e) { borrowOrOprSuccess = false; if (jedis != null) jedisPool.returnBrokenResource(jedis); } finally { if (borrowOrOprSuccess) jedisPool.returnResource(jedis); } return result; } @Override public void putObject(Object key, Object value) { Jedis jedis = null; boolean borrowOrOprSuccess = true; try { jedis = jedisPool.getResource(); jedis.select(DB_INDEX); byte[] keys = getKey(key).getBytes(UTF8); jedis.set(keys, SerializeUtil.serialize(value)); logger.debug("添加缓存--------" + this.id + " | " +keys.toString() + ":" + value.toString() ); getSize(); } catch (Exception e) { borrowOrOprSuccess = false; if (jedis != null) jedisPool.returnBrokenResource(jedis); } finally { if (borrowOrOprSuccess) jedisPool.returnResource(jedis); } } @Override public Object getObject(Object key) { Jedis jedis = null; Object value = null; boolean borrowOrOprSuccess = true; try { jedis = jedisPool.getResource(); jedis.select(DB_INDEX); byte[] keys = getKey(key).getBytes(UTF8); value = SerializeUtil.unserialize(jedis.get(getKey(key).getBytes(UTF8))); logger.debug("从缓存中获取-----" + this.id + " | "+keys.toString() + ":" + value.toString()); getSize(); } catch (Exception e) { borrowOrOprSuccess = false; if (jedis != null) jedisPool.returnBrokenResource(jedis); } finally { if (borrowOrOprSuccess) jedisPool.returnResource(jedis); } return value; } @Override public Object removeObject(Object key) { Jedis jedis = null; Object value = null; boolean borrowOrOprSuccess = true; try { jedis = jedisPool.getResource(); jedis.select(DB_INDEX); byte[] keys = getKey(key).getBytes(UTF8); value = jedis.del(getKey(key).getBytes(UTF8)); logger.debug("LRU算法从缓存中移除-----" + this.id + " | " +keys.toString() + ":" + value.toString()); getSize(); } catch (Exception e) { borrowOrOprSuccess = false; if (jedis != null) jedisPool.returnBrokenResource(jedis); } finally { if (borrowOrOprSuccess) jedisPool.returnResource(jedis); } return value; } @Override public void clear() { Jedis jedis = null; boolean borrowOrOprSuccess = true; try { jedis = jedisPool.getResource(); jedis.select(DB_INDEX); // 如果有删除操作,会影响到整个表中的数据,因此要清空一个mapper的缓存(一个mapper的不同数据操作对应不同的key) Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF8)); logger.debug("出现CUD操作,清空对应Mapper缓存======>" + keys.size()); for (byte[] key : keys) { jedis.del(key); } // 下面是网上流传的方法,极大的降低系统性能,没起到加入缓存应有的作用,这是不可取的。 // jedis.flushDB(); // jedis.flushAll(); } catch (Exception e) { borrowOrOprSuccess = false; if (jedis != null) jedisPool.returnBrokenResource(jedis); } finally { if (borrowOrOprSuccess) jedisPool.returnResource(jedis); } } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } }
package org.mybatis.caches.memcached; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; /** * The Memcached-based Cache implementation. * * @author Simone Tripodi */ public final class MemcachedCache implements Cache { private static final MemcachedClientWrapper MEMCACHED_CLIENT = new MemcachedClientWrapper(); /** * The {@link ReadWriteLock}. */ private final ReadWriteLock readWriteLock = new DummyReadWriteLock(); /** * The cache id. */ private final String id; /** * Builds a new Memcached-based Cache. * * @param id the Mapper id. */ public MemcachedCache(final String id) { this.id = id; } /** * {@inheritDoc} */ public void clear() { MEMCACHED_CLIENT.removeGroup(this.id); } /** * {@inheritDoc} */ public String getId() { return this.id; } /** * {@inheritDoc} */ public Object getObject(Object key) { return MEMCACHED_CLIENT.getObject(key); } /** * {@inheritDoc} */ public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } /** * {@inheritDoc} */ public int getSize() { return Integer.MAX_VALUE; } /** * {@inheritDoc} */ public void putObject(Object key, Object value) { MEMCACHED_CLIENT.putObject(key, value, this.id); } /** * {@inheritDoc} */ public Object removeObject(Object key) { return MEMCACHED_CLIENT.removeObject(key); } }
package org.mybatis.caches.ehcache; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; /** * Cache adapter for Ehcache. * * @version $Id: EhcacheCache.java 3454 2010-12-29 20:35:44Z simone.tripodi $ */ public final class EhcacheCache implements Cache { /** * The cache manager reference. */ private static final CacheManager CACHE_MANAGER = createCacheManager(); /** * Looks for "/ehcache.xml" classpath resource and builds the relative * {@code CacheManager}; if it's no found or it is impossible to load it, * returns the default manager. * * @return the application cache manager. */ private static CacheManager createCacheManager() { CacheManager cacheManager; InputStream input = EhcacheCache.class.getResourceAsStream("/ehcache.xml"); if (input != null) { try { cacheManager = CacheManager.create(input); } catch (Throwable t) { cacheManager = CacheManager.create(); } finally { try { input.close(); } catch (IOException e) { } } } else { cacheManager = CacheManager.create(); } return cacheManager; } /** * The {@code ReadWriteLock}. */ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); /** * The cache id. */ private final String id; /** * * * @param id */ public EhcacheCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; if (!CACHE_MANAGER.cacheExists(this.id)) { CACHE_MANAGER.addCache(this.id); } } /** * {@inheritDoc} */ public void clear() { this.getCache().removeAll(); } /** * {@inheritDoc} */ public String getId() { return this.id; } /** * {@inheritDoc} */ public Object getObject(Object key) { try { Element cachedElement = this.getCache().get(key.hashCode()); if (cachedElement == null) { return null; } return cachedElement.getObjectValue(); } catch (Throwable t) { throw new CacheException(t); } } /** * {@inheritDoc} */ public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } /** * {@inheritDoc} */ public int getSize() { try { return this.getCache().getSize(); } catch (Throwable t) { throw new CacheException(t); } } /** * {@inheritDoc} */ public void putObject(Object key, Object value) { try { this.getCache().put(new Element(key.hashCode(), value)); } catch (Throwable t) { throw new CacheException(t); } } /** * {@inheritDoc} */ public Object removeObject(Object key) { try { Object obj = this.getObject(key); this.getCache().remove(key.hashCode()); return obj; } catch (Throwable t) { throw new CacheException(t); } } /** * Returns the ehcache manager for this cache. * * @return the ehcache manager for this cache. */ private Ehcache getCache() { return CACHE_MANAGER.getCache(this.id); } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Cache)) { return false; } Cache otherCache = (Cache) obj; return this.id.equals(otherCache.getId()); } /** * {@inheritDoc} */ @Override public int hashCode() { return this.id.hashCode(); } /** * {@inheritDoc} */ @Override public String toString() { return "EHCache {" + this.id + "}"; } }