diff --git a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java index fa28b2913c..72ae884a20 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -65,6 +65,17 @@ public class EhCacheCache implements Cache { return (element != null ? new SimpleValueWrapper(element.getObjectValue()) : null); } + @Override + @SuppressWarnings("unchecked") + public T get(Object key, Class type) { + Element element = this.cache.get(key); + Object value = (element != null ? element.getObjectValue() : null); + if (type != null && !type.isInstance(value)) { + throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); + } + return (T) value; + } + @Override public void put(Object key, Object value) { this.cache.put(new Element(key, value)); diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java index 536f9fc20b..c95cd6618f 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/JCacheCache.java @@ -82,6 +82,16 @@ public class JCacheCache implements Cache { return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null); } + @Override + @SuppressWarnings("unchecked") + public T get(Object key, Class type) { + Object value = fromStoreValue(this.cache.get(key)); + if (type != null && !type.isInstance(value)) { + throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); + } + return (T) value; + } + @Override @SuppressWarnings("unchecked") public void put(Object key, Object value) { diff --git a/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java b/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java index abda2b7caf..adc931abe3 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java +++ b/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -62,6 +62,11 @@ public class TransactionAwareCacheDecorator implements Cache { return this.targetCache.get(key); } + @Override + public T get(Object key, Class type) { + return this.targetCache.get(key, type); + } + @Override public void put(final Object key, final Object value) { if (TransactionSynchronizationManager.isSynchronizationActive()) { diff --git a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java index 63fd1546a5..a76ddb98ed 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java @@ -20,7 +20,6 @@ import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; import net.sf.ehcache.config.CacheConfiguration; - import org.junit.Before; import org.junit.Test; @@ -74,6 +73,9 @@ public class EhCacheCacheTests { assertNull(cache.get(key)); cache.put(key, value); assertEquals(value, cache.get(key).get()); + assertEquals(value, cache.get(key, String.class)); + assertEquals(value, cache.get(key, Object.class)); + assertEquals(value, cache.get(key, null)); } @Test diff --git a/spring-context/src/main/java/org/springframework/cache/Cache.java b/spring-context/src/main/java/org/springframework/cache/Cache.java index dbfa1cba84..2051d67a0b 100644 --- a/spring-context/src/main/java/org/springframework/cache/Cache.java +++ b/spring-context/src/main/java/org/springframework/cache/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -39,14 +39,34 @@ public interface Cache { Object getNativeCache(); /** - * Return the value to which this cache maps the specified key. Returns - * {@code null} if the cache contains no mapping for this key. - * @param key key whose associated value is to be returned. + * Return the value to which this cache maps the specified key. + *

Returns {@code null} if the cache contains no mapping for this key; + * otherwise, the cached value (which may be {@code null} itself) will + * be returned in a {@link ValueWrapper}. + * @param key the key whose associated value is to be returned * @return the value to which this cache maps the specified key, - * or {@code null} if the cache contains no mapping for this key + * contained within a {@link ValueWrapper} which may also hold + * a cached {@code null} value. A straight {@code null} being + * returned means that the cache contains no mapping for this key. + * @see #get(Object, Class) */ ValueWrapper get(Object key); + /** + * Return the value to which this cache maps the specified key, + * generically specifying a type that return value will be cast to. + *

Note: This variant of {@code get} does not allow for differentiating + * between a cached {@code null} value and no cache entry found at all. + * Use the standard {@link #get(Object)} variant for that purpose instead. + * @param key the key whose associated value is to be returned + * @param type the required type of the returned value + * @return the value to which this cache maps the specified key + * (which may be {@code null} itself), or also {@code null} if + * the cache contains no mapping for this key + * @see #get(Object) + */ + T get(Object key, Class type); + /** * Associate the specified value with the specified key in this cache. *

If the cache previously contained a mapping for this key, the old diff --git a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java index 7780357153..822d100664 100644 --- a/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java +++ b/spring-context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java @@ -16,13 +16,13 @@ package org.springframework.cache.concurrent; -import org.springframework.cache.Cache; -import org.springframework.cache.support.SimpleValueWrapper; - import java.io.Serializable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.springframework.cache.Cache; +import org.springframework.cache.support.SimpleValueWrapper; + /** * Simple {@link Cache} implementation based on the core JDK * {@code java.util.concurrent} package. @@ -103,6 +103,16 @@ public class ConcurrentMapCache implements Cache { return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null); } + @Override + @SuppressWarnings("unchecked") + public T get(Object key, Class type) { + Object value = fromStoreValue(this.store.get(key)); + if (type != null && !type.isInstance(value)) { + throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); + } + return (T) value; + } + @Override public void put(Object key, Object value) { this.store.put(key, toStoreValue(value)); diff --git a/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java b/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java index f8ffe0e729..c76c79731d 100644 --- a/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java +++ b/spring-context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -93,6 +93,11 @@ public class NoOpCacheManager implements CacheManager { return null; } + @Override + public T get(Object key, Class type) { + return null; + } + @Override public String getName() { return this.name; diff --git a/spring-context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java b/spring-context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java index 79b39b60a6..0e9ecbf77e 100644 --- a/spring-context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java +++ b/spring-context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2010-2013 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. @@ -48,6 +48,7 @@ public class NoOpCacheManagerTests { Object key = new Object(); cache.put(key, new Object()); assertNull(cache.get(key)); + assertNull(cache.get(key, Object.class)); assertNull(cache.getNativeCache()); } diff --git a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java index fdc13fbd64..62d1993b87 100644 --- a/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java +++ b/spring-context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 the original author or authors. + * Copyright 2010-2013 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. @@ -64,6 +64,9 @@ public class ConcurrentCacheTests { assertNull(cache.get(key)); cache.put(key, value); assertEquals(value, cache.get(key).get()); + assertEquals(value, cache.get(key, String.class)); + assertEquals(value, cache.get(key, Object.class)); + assertEquals(value, cache.get(key, null)); } @Test