diff --git a/src/main/java/org/apache/ibatis/cache/CacheDecorator.java b/src/main/java/org/apache/ibatis/cache/CacheDecorator.java new file mode 100644 index 00000000000..48f7722eda6 --- /dev/null +++ b/src/main/java/org/apache/ibatis/cache/CacheDecorator.java @@ -0,0 +1,71 @@ +/** + * Copyright 2009-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.cache; + +import java.util.concurrent.locks.ReadWriteLock; + +/** + * abstract cache decorator. + * @author wuwen + */ +public abstract class CacheDecorator implements Cache { + + private Cache delegate; + + public CacheDecorator(Cache cache) { + this.delegate = cache; + } + + @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(); + } + + @Override + public ReadWriteLock getReadWriteLock() { + return delegate.getReadWriteLock(); + } + + public Cache getDelegate() { + return delegate; + } + +} 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 6901a5212af..260b16a5450 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/BlockingCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; import org.apache.ibatis.cache.CacheException; /** @@ -34,31 +34,20 @@ * @author Eduardo Macarron * */ -public class BlockingCache implements Cache { +public class BlockingCache extends CacheDecorator { 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 +56,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); } @@ -80,16 +69,6 @@ public Object removeObject(Object key) { releaseLock(key); return null; } - - @Override - public void clear() { - delegate.clear(); - } - - @Override - public ReadWriteLock getReadWriteLock() { - return null; - } private ReentrantLock getLockForKey(Object key) { ReentrantLock lock = new ReentrantLock(); @@ -103,7 +82,7 @@ private void acquireLock(Object key) { try { boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); if (!acquired) { - throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId()); + throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + getId()); } } catch (InterruptedException e) { throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e); 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 e2443f51455..4ffe1a4f69f 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,37 +17,26 @@ import java.util.Deque; import java.util.LinkedList; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * FIFO (first in, first out) cache decorator * * @author Clinton Begin */ -public class FifoCache implements Cache { +public class FifoCache extends CacheDecorator { - private final Cache delegate; private 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; } @@ -55,35 +44,20 @@ 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(); } - @Override - public ReadWriteLock getReadWriteLock() { - return null; - } - 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 17824ae2654..f59149ee25e 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,46 +15,30 @@ */ package org.apache.ibatis.cache.decorators; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; /** * @author Clinton Begin */ -public class LoggingCache implements Cache { +public class LoggingCache extends CacheDecorator { private Log log; - private Cache delegate; - protected int requests = 0; - protected int hits = 0; + protected volatile int requests = 0; + protected volatile int hits = 0; 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++; } @@ -64,33 +48,25 @@ 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 ReadWriteLock getReadWriteLock() { - return null; - } - @Override public int hashCode() { - return delegate.hashCode(); + return getDelegate().hashCode(); } @Override public boolean equals(Object obj) { - return delegate.equals(obj); + return getDelegate().equals(obj); } private double getHitRatio() { return (double) hits / (double) requests; } + public int getRequests() { + return requests; + } + + public int getHits() { + return hits; + } } 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 90340e14191..f700f4b559f 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/LruCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,36 +17,25 @@ import java.util.LinkedHashMap; import java.util.Map; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * Lru (least recently used) cache decorator * * @author Clinton Begin */ -public class LruCache implements Cache { +public class LruCache extends CacheDecorator { - 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; @@ -64,36 +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(); } - @Override - public ReadWriteLock getReadWriteLock() { - return null; - } - 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 f4e1c1cf007..8de4acbf8da 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/ScheduledCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,21 +15,19 @@ */ package org.apache.ibatis.cache.decorators; -import java.util.concurrent.locks.ReadWriteLock; - import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * @author Clinton Begin */ -public class ScheduledCache implements Cache { +public class ScheduledCache extends CacheDecorator { - private Cache delegate; protected long clearInterval; protected long lastClear; public ScheduledCache(Cache delegate) { - this.delegate = delegate; + super(delegate); this.clearInterval = 60 * 60 * 1000; // 1 hour this.lastClear = System.currentTimeMillis(); } @@ -38,53 +36,43 @@ 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 ReadWriteLock getReadWriteLock() { - return null; + super.clear(); } @Override public int hashCode() { - return delegate.hashCode(); + return getDelegate().hashCode(); } @Override public boolean equals(Object obj) { - return delegate.equals(obj); + return getDelegate().equals(obj); } 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 2b5e3ad1e91..cdf8d8029e8 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,37 +23,25 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; import org.apache.ibatis.cache.CacheException; import org.apache.ibatis.io.Resources; /** * @author Clinton Begin */ -public class SerializedCache implements Cache { - - private Cache delegate; +public class SerializedCache extends CacheDecorator { public SerializedCache(Cache delegate) { - this.delegate = delegate; - } - - @Override - public String getId() { - return delegate.getId(); - } - - @Override - public int getSize() { - return delegate.getSize(); + super(delegate); } @Override public void putObject(Object key, Object object) { if (object == null || object instanceof Serializable) { - delegate.putObject(key, serialize((Serializable) object)); + super.putObject(key, serialize((Serializable) object)); } else { throw new CacheException("SharedCache failed to make a copy of a non-serializable object: " + object); } @@ -61,33 +49,18 @@ public void putObject(Object key, Object 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 ReadWriteLock getReadWriteLock() { - return null; - } - @Override public int hashCode() { - return delegate.hashCode(); + return getDelegate().hashCode(); } @Override public boolean equals(Object obj) { - return delegate.equals(obj); + return getDelegate().equals(obj); } private byte[] serialize(Serializable value) { 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 6c4b5610f16..996e302ed94 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SoftCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ import java.lang.ref.SoftReference; import java.util.Deque; import java.util.LinkedList; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * Soft Reference cache decorator @@ -29,28 +29,22 @@ * * @author Clinton Begin */ -public class SoftCache implements Cache { +public class SoftCache extends CacheDecorator { 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(); } @@ -61,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 +83,7 @@ public Object getObject(Object key) { @Override public Object removeObject(Object key) { removeGarbageCollectedItems(); - return delegate.removeObject(key); + return super.removeObject(key); } @Override @@ -98,18 +92,13 @@ public void clear() { hardLinksToAvoidGarbageCollection.clear(); } removeGarbageCollectedItems(); - delegate.clear(); - } - - @Override - public ReadWriteLock getReadWriteLock() { - return null; + 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 40f775b9f72..1e8350d54ca 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/SynchronizedCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,64 +15,52 @@ */ package org.apache.ibatis.cache.decorators; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * @author Clinton Begin */ -public class SynchronizedCache implements Cache { +public class SynchronizedCache extends CacheDecorator { - private Cache delegate; - 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(); + super.clear(); } @Override public int hashCode() { - return delegate.hashCode(); + return getDelegate().hashCode(); } @Override public boolean equals(Object obj) { - return delegate.equals(obj); - } - - @Override - public ReadWriteLock getReadWriteLock() { - return null; + return getDelegate().equals(obj); } } 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 65dd69f3bd7..7f03e0c34ee 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/TransactionalCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; @@ -36,36 +36,25 @@ * @author Clinton Begin * @author Eduardo Macarron */ -public class TransactionalCache implements Cache { +public class TransactionalCache extends CacheDecorator { private static final Log log = LogFactory.getLog(TransactionalCache.class); - private Cache delegate; private boolean clearOnCommit; private Map entriesToAddOnCommit; private 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); } @@ -77,11 +66,6 @@ public Object getObject(Object key) { } } - @Override - public ReadWriteLock getReadWriteLock() { - return null; - } - @Override public void putObject(Object key, Object object) { entriesToAddOnCommit.put(key, object); @@ -100,7 +84,7 @@ public void clear() { public void commit() { if (clearOnCommit) { - delegate.clear(); + super.clear(); } flushPendingEntries(); reset(); @@ -119,11 +103,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); } } } @@ -131,7 +115,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 notifiying 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 033f71d696b..c9ad7b6bcaf 100644 --- a/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java +++ b/src/main/java/org/apache/ibatis/cache/decorators/WeakCache.java @@ -1,5 +1,5 @@ /** - * Copyright 2009-2015 the original author or authors. + * Copyright 2009-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ import java.lang.ref.WeakReference; import java.util.Deque; import java.util.LinkedList; -import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; +import org.apache.ibatis.cache.CacheDecorator; /** * Weak Reference cache decorator. @@ -29,28 +29,22 @@ * * @author Clinton Begin */ -public class WeakCache implements Cache { +public class WeakCache extends CacheDecorator { 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 +54,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 { hardLinksToAvoidGarbageCollection.addFirst(result); if (hardLinksToAvoidGarbageCollection.size() > numberOfHardLinks) { @@ -85,25 +79,20 @@ public Object getObject(Object key) { @Override public Object removeObject(Object key) { removeGarbageCollectedItems(); - return delegate.removeObject(key); + return super.removeObject(key); } @Override public void clear() { hardLinksToAvoidGarbageCollection.clear(); removeGarbageCollectedItems(); - delegate.clear(); - } - - @Override - public ReadWriteLock getReadWriteLock() { - return null; + 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/test/java/org/apache/ibatis/cache/CacheDecoratorTest.java b/src/test/java/org/apache/ibatis/cache/CacheDecoratorTest.java new file mode 100644 index 00000000000..b07c2a1088a --- /dev/null +++ b/src/test/java/org/apache/ibatis/cache/CacheDecoratorTest.java @@ -0,0 +1,60 @@ +/** + * Copyright 2009-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.ibatis.cache; + +import org.apache.ibatis.cache.decorators.*; +import org.apache.ibatis.cache.impl.PerpetualCache; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author wuwen + */ +public class CacheDecoratorTest { + + @Test + public void getSpecifiedDecorator() { + Cache cache = new PerpetualCache("default"); + cache = new LruCache(cache); + cache = new LoggingCache(cache); + cache = new SynchronizedCache(cache); + + cache.putObject("hello", System.currentTimeMillis()); + + cache.getObject("hello"); + + LoggingCache loggingCache = findCacheDecorator((CacheDecorator)cache, LoggingCache.class); + + assertNotNull(loggingCache); + assertEquals(1,loggingCache.getHits()); + + } + + private T findCacheDecorator(CacheDecorator cache, Class type) { + Cache delegate = cache.getDelegate(); + + if (delegate.getClass().equals(type)) { + return (T) delegate; + } else if (delegate instanceof CacheDecorator) { + return findCacheDecorator((CacheDecorator)delegate, type); + } + + return null; + } + +}