diff --git a/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java b/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java index b70fc0c61f8..62542367987 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java @@ -21,6 +21,7 @@ import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; +import org.apache.ibatis.cache.impl.DelegateCache; /** *

@@ -34,31 +35,20 @@ * * @author Eduardo Macarron */ -public class BlockingCache implements Cache { +public class BlockingCache extends DelegateCache { private long timeout; - private final Cache delegate; private final ConcurrentHashMap locks; public BlockingCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.locks = new ConcurrentHashMap<>(); } - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - @Override public void putObject(Object key, Object value) { try { - delegate.putObject(key, value); + super.putObject(key, value); } finally { releaseLock(key); } @@ -67,7 +57,7 @@ public void putObject(Object key, Object value) { @Override public Object getObject(Object key) { acquireLock(key); - Object value = delegate.getObject(key); + Object value = super.getObject(key); if (value != null) { releaseLock(key); } @@ -81,11 +71,6 @@ public Object removeObject(Object key) { return null; } - @Override - public void clear() { - delegate.clear(); - } - private void acquireLock(Object key) { CountDownLatch newLatch = new CountDownLatch(1); while (true) { @@ -98,7 +83,7 @@ private void acquireLock(Object key) { boolean acquired = latch.await(timeout, TimeUnit.MILLISECONDS); if (!acquired) { throw new CacheException( - "Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId()); + "Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + super.getId()); } } else { latch.await(); diff --git a/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java b/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java index f9550c22726..935e5b65917 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java @@ -19,34 +19,24 @@ import java.util.LinkedList; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * FIFO (first in, first out) cache decorator. * * @author Clinton Begin */ -public class FifoCache implements Cache { +public class FifoCache extends DelegateCache { - private final Cache delegate; private final Deque keyList; private int size; public FifoCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.keyList = new LinkedList<>(); this.size = 1024; } - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - public void setSize(int size) { this.size = size; } @@ -54,22 +44,12 @@ public void setSize(int size) { @Override public void putObject(Object key, Object value) { cycleKeyList(key); - delegate.putObject(key, value); - } - - @Override - public Object getObject(Object key) { - return delegate.getObject(key); - } - - @Override - public Object removeObject(Object key) { - return delegate.removeObject(key); + super.putObject(key, value); } @Override public void clear() { - delegate.clear(); + super.clear(); keyList.clear(); } @@ -77,7 +57,7 @@ private void cycleKeyList(Object key) { keyList.addLast(key); if (keyList.size() > size) { Object oldestKey = keyList.removeFirst(); - delegate.removeObject(oldestKey); + super.removeObject(oldestKey); } } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java b/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java index 6ff00cb2e06..9665b56b378 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java @@ -16,43 +16,28 @@ package org.apache.ibatis.cache.decorators; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; /** * @author Clinton Begin */ -public class LoggingCache implements Cache { +public class LoggingCache extends DelegateCache { private final Log log; - private final Cache delegate; protected int requests; protected int hits; public LoggingCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.log = LogFactory.getLog(getId()); } - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - - @Override - public void putObject(Object key, Object object) { - delegate.putObject(key, object); - } - @Override public Object getObject(Object key) { requests++; - final Object value = delegate.getObject(key); + final Object value = super.getObject(key); if (value != null) { hits++; } @@ -62,26 +47,6 @@ public Object getObject(Object key) { return value; } - @Override - public Object removeObject(Object key) { - return delegate.removeObject(key); - } - - @Override - public void clear() { - delegate.clear(); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); - } - private double getHitRatio() { return (double) hits / (double) requests; } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java b/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java index 1c593499471..e6057d6c23e 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java @@ -19,33 +19,23 @@ import java.util.Map; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * Lru (least recently used) cache decorator. * * @author Clinton Begin */ -public class LruCache implements Cache { +public class LruCache extends DelegateCache { - private final Cache delegate; private Map keyMap; private Object eldestKey; public LruCache(Cache delegate) { - this.delegate = delegate; + super(delegate); setSize(1024); } - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - public void setSize(final int size) { keyMap = new LinkedHashMap(size, .75F, true) { private static final long serialVersionUID = 4267176411845948333L; @@ -63,31 +53,26 @@ protected boolean removeEldestEntry(Map.Entry eldest) { @Override public void putObject(Object key, Object value) { - delegate.putObject(key, value); + super.putObject(key, value); cycleKeyList(key); } @Override public Object getObject(Object key) { keyMap.get(key); // touch - return delegate.getObject(key); - } - - @Override - public Object removeObject(Object key) { - return delegate.removeObject(key); + return super.getObject(key); } @Override public void clear() { - delegate.clear(); + super.clear(); keyMap.clear(); } private void cycleKeyList(Object key) { keyMap.put(key, key); if (eldestKey != null) { - delegate.removeObject(eldestKey); + super.removeObject(eldestKey); eldestKey = null; } } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java b/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java index 2fb059da846..3d13dc58c66 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java @@ -18,18 +18,18 @@ import java.util.concurrent.TimeUnit; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * @author Clinton Begin */ -public class ScheduledCache implements Cache { +public class ScheduledCache extends DelegateCache { - private final Cache delegate; protected long clearInterval; protected long lastClear; public ScheduledCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.clearInterval = TimeUnit.HOURS.toMillis(1); this.lastClear = System.currentTimeMillis(); } @@ -38,48 +38,33 @@ public void setClearInterval(long clearInterval) { this.clearInterval = clearInterval; } - @Override - public String getId() { - return delegate.getId(); - } - @Override public int getSize() { clearWhenStale(); - return delegate.getSize(); + return super.getSize(); } @Override public void putObject(Object key, Object object) { clearWhenStale(); - delegate.putObject(key, object); + super.putObject(key, object); } @Override public Object getObject(Object key) { - return clearWhenStale() ? null : delegate.getObject(key); + return clearWhenStale() ? null : super.getObject(key); } @Override public Object removeObject(Object key) { clearWhenStale(); - return delegate.removeObject(key); + return super.removeObject(key); } @Override public void clear() { lastClear = System.currentTimeMillis(); - delegate.clear(); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); + super.clear(); } private boolean clearWhenStale() { diff --git a/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java b/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java index 5726c8d2556..b419dd1ad2c 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java @@ -26,28 +26,17 @@ import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; +import org.apache.ibatis.cache.impl.DelegateCache; import org.apache.ibatis.io.Resources; import org.apache.ibatis.io.SerialFilterChecker; /** * @author Clinton Begin */ -public class SerializedCache implements Cache { - - private final Cache delegate; +public class SerializedCache extends DelegateCache { public SerializedCache(Cache delegate) { - this.delegate = delegate; - } - - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); + super(delegate); } @Override @@ -55,35 +44,15 @@ public void putObject(Object key, Object object) { if ((object != null) && !(object instanceof Serializable)) { throw new CacheException("SharedCache failed to make a copy of a non-serializable object: " + object); } - delegate.putObject(key, serialize((Serializable) object)); + super.putObject(key, serialize((Serializable) object)); } @Override public Object getObject(Object key) { - Object object = delegate.getObject(key); + Object object = super.getObject(key); return object == null ? null : deserialize((byte[]) object); } - @Override - public Object removeObject(Object key) { - return delegate.removeObject(key); - } - - @Override - public void clear() { - delegate.clear(); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); - } - private byte[] serialize(Serializable value) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) { diff --git a/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java b/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java index daef435e890..e1b3f400bcb 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java @@ -21,6 +21,7 @@ import java.util.LinkedList; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * Soft Reference cache decorator. @@ -29,28 +30,22 @@ * * @author Clinton Begin */ -public class SoftCache implements Cache { +public class SoftCache extends DelegateCache { private final Deque hardLinksToAvoidGarbageCollection; private final ReferenceQueue queueOfGarbageCollectedEntries; - private final Cache delegate; private int numberOfHardLinks; public SoftCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.numberOfHardLinks = 256; this.hardLinksToAvoidGarbageCollection = new LinkedList<>(); this.queueOfGarbageCollectedEntries = new ReferenceQueue<>(); } - @Override - public String getId() { - return delegate.getId(); - } - @Override public int getSize() { removeGarbageCollectedItems(); - return delegate.getSize(); + return super.getSize(); } public void setSize(int size) { @@ -60,18 +55,18 @@ public void setSize(int size) { @Override public void putObject(Object key, Object value) { removeGarbageCollectedItems(); - delegate.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries)); + super.putObject(key, new SoftEntry(key, value, queueOfGarbageCollectedEntries)); } @Override public Object getObject(Object key) { Object result = null; @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache - SoftReference softReference = (SoftReference) delegate.getObject(key); + SoftReference softReference = (SoftReference) super.getObject(key); if (softReference != null) { result = softReference.get(); if (result == null) { - delegate.removeObject(key); + super.removeObject(key); } else { // See #586 (and #335) modifications need more than a read lock synchronized (hardLinksToAvoidGarbageCollection) { @@ -89,7 +84,7 @@ public Object getObject(Object key) { public Object removeObject(Object key) { removeGarbageCollectedItems(); @SuppressWarnings("unchecked") - SoftReference softReference = (SoftReference) delegate.removeObject(key); + SoftReference softReference = (SoftReference) super.removeObject(key); return softReference == null ? null : softReference.get(); } @@ -99,13 +94,13 @@ public void clear() { hardLinksToAvoidGarbageCollection.clear(); } removeGarbageCollectedItems(); - delegate.clear(); + super.clear(); } private void removeGarbageCollectedItems() { SoftEntry sv; while ((sv = (SoftEntry) queueOfGarbageCollectedEntries.poll()) != null) { - delegate.removeObject(sv.key); + super.removeObject(sv.key); } } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java b/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java index 72f1dbccf85..35c19f14b7f 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java @@ -16,56 +16,40 @@ package org.apache.ibatis.cache.decorators; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * @author Clinton Begin */ -public class SynchronizedCache implements Cache { - - private final Cache delegate; +public class SynchronizedCache extends DelegateCache { public SynchronizedCache(Cache delegate) { - this.delegate = delegate; - } - - @Override - public String getId() { - return delegate.getId(); + super(delegate); } @Override public synchronized int getSize() { - return delegate.getSize(); + return super.getSize(); } @Override public synchronized void putObject(Object key, Object object) { - delegate.putObject(key, object); + super.putObject(key, object); } @Override public synchronized Object getObject(Object key) { - return delegate.getObject(key); + return super.getObject(key); } @Override public synchronized Object removeObject(Object key) { - return delegate.removeObject(key); + return super.removeObject(key); } @Override public synchronized void clear() { - delegate.clear(); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return delegate.equals(obj); + super.clear(); } } diff --git a/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java b/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java index cb022484854..b314c8ee8be 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java @@ -21,6 +21,7 @@ import java.util.Set; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; @@ -35,36 +36,25 @@ * @author Clinton Begin * @author Eduardo Macarron */ -public class TransactionalCache implements Cache { +public class TransactionalCache extends DelegateCache { private static final Log log = LogFactory.getLog(TransactionalCache.class); - private final Cache delegate; private boolean clearOnCommit; private final Map entriesToAddOnCommit; private final Set entriesMissedInCache; public TransactionalCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.clearOnCommit = false; this.entriesToAddOnCommit = new HashMap<>(); this.entriesMissedInCache = new HashSet<>(); } - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); - } - @Override public Object getObject(Object key) { // issue #116 - Object object = delegate.getObject(key); + Object object = super.getObject(key); if (object == null) { entriesMissedInCache.add(key); } @@ -93,7 +83,7 @@ public void clear() { public void commit() { if (clearOnCommit) { - delegate.clear(); + super.clear(); } flushPendingEntries(); reset(); @@ -112,11 +102,11 @@ private void reset() { private void flushPendingEntries() { for (Map.Entry entry : entriesToAddOnCommit.entrySet()) { - delegate.putObject(entry.getKey(), entry.getValue()); + super.putObject(entry.getKey(), entry.getValue()); } for (Object entry : entriesMissedInCache) { if (!entriesToAddOnCommit.containsKey(entry)) { - delegate.putObject(entry, null); + super.putObject(entry, null); } } } @@ -124,7 +114,7 @@ private void flushPendingEntries() { private void unlockMissedEntries() { for (Object entry : entriesMissedInCache) { try { - delegate.removeObject(entry); + super.removeObject(entry); } catch (Exception e) { log.warn("Unexpected exception while notifying a rollback to the cache adapter. " + "Consider upgrading your cache adapter to the latest version. Cause: " + e); diff --git a/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java b/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java index 8af6f1d0b5a..b0c8aafa778 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java @@ -21,6 +21,7 @@ import java.util.LinkedList; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.impl.DelegateCache; /** * Weak Reference cache decorator. @@ -29,28 +30,22 @@ * * @author Clinton Begin */ -public class WeakCache implements Cache { +public class WeakCache extends DelegateCache { private final Deque hardLinksToAvoidGarbageCollection; private final ReferenceQueue queueOfGarbageCollectedEntries; - private final Cache delegate; private int numberOfHardLinks; public WeakCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.numberOfHardLinks = 256; this.hardLinksToAvoidGarbageCollection = new LinkedList<>(); this.queueOfGarbageCollectedEntries = new ReferenceQueue<>(); } - @Override - public String getId() { - return delegate.getId(); - } - @Override public int getSize() { removeGarbageCollectedItems(); - return delegate.getSize(); + return super.getSize(); } public void setSize(int size) { @@ -60,18 +55,18 @@ public void setSize(int size) { @Override public void putObject(Object key, Object value) { removeGarbageCollectedItems(); - delegate.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries)); + super.putObject(key, new WeakEntry(key, value, queueOfGarbageCollectedEntries)); } @Override public Object getObject(Object key) { Object result = null; @SuppressWarnings("unchecked") // assumed delegate cache is totally managed by this cache - WeakReference weakReference = (WeakReference) delegate.getObject(key); + WeakReference weakReference = (WeakReference) super.getObject(key); if (weakReference != null) { result = weakReference.get(); if (result == null) { - delegate.removeObject(key); + super.removeObject(key); } else { synchronized (hardLinksToAvoidGarbageCollection) { hardLinksToAvoidGarbageCollection.addFirst(result); @@ -88,7 +83,7 @@ public Object getObject(Object key) { public Object removeObject(Object key) { removeGarbageCollectedItems(); @SuppressWarnings("unchecked") - WeakReference weakReference = (WeakReference) delegate.removeObject(key); + WeakReference weakReference = (WeakReference) super.removeObject(key); return weakReference == null ? null : weakReference.get(); } @@ -98,13 +93,13 @@ public void clear() { hardLinksToAvoidGarbageCollection.clear(); } removeGarbageCollectedItems(); - delegate.clear(); + super.clear(); } private void removeGarbageCollectedItems() { WeakEntry sv; while ((sv = (WeakEntry) queueOfGarbageCollectedEntries.poll()) != null) { - delegate.removeObject(sv.key); + super.removeObject(sv.key); } } diff --git a/src/main/java/org/apache/ibatis/cache/impl/DelegateCache.java b/src/main/java/org/apache/ibatis/cache/impl/DelegateCache.java new file mode 100644 index 00000000000..0b6cded9d96 --- /dev/null +++ b/src/main/java/org/apache/ibatis/cache/impl/DelegateCache.java @@ -0,0 +1,42 @@ +package org.apache.ibatis.cache.impl; + +import org.apache.ibatis.cache.Cache; + +public abstract class DelegateCache implements Cache { + + private final Cache delegate; + + public DelegateCache(Cache delegate) { + this.delegate = delegate; + } + + @Override + public String getId() { + return delegate.getId(); + } + + @Override + public void putObject(Object key, Object value) { + delegate.putObject(key, value); + } + + @Override + public Object getObject(Object key) { + return delegate.getObject(key); + } + + @Override + public Object removeObject(Object key) { + return delegate.removeObject(key); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public int getSize() { + return delegate.getSize(); + } +}