From a5a925e37a9c481e59eaa49b871aad054f41fa83 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 2 Dec 2011 11:29:11 +0100 Subject: [PATCH] DATACMNS-77 - Introduced caching inside ClassTypeInformation. ClassTypeInformation now holds a cache for Class to TypeInformation mappings. It also exposes constants for Object, Collection, Set, List and Map TypeInformations. --- .../data/util/ClassTypeInformation.java | 40 +++++++++++++++++-- .../util/ClassTypeInformationUnitTests.java | 10 +++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/util/ClassTypeInformation.java b/spring-data-commons-core/src/main/java/org/springframework/data/util/ClassTypeInformation.java index 1e1755a03..a66412696 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/util/ClassTypeInformation.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/util/ClassTypeInformation.java @@ -15,20 +15,44 @@ */ package org.springframework.data.util; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import org.springframework.util.Assert; /** - * PropertyPath information for a plain {@link Class}. + * {@link TypeInformation} for a plain {@link Class}. * * @author Oliver Gierke */ +@SuppressWarnings({ "unchecked", "rawtypes" }) public class ClassTypeInformation extends TypeDiscoverer { + public static final TypeInformation COLLECTION = new ClassTypeInformation(Collection.class); + public static final TypeInformation LIST = new ClassTypeInformation(List.class); + public static final TypeInformation SET = new ClassTypeInformation(Set.class); + public static final TypeInformation MAP = new ClassTypeInformation(Map.class); + public static final TypeInformation OBJECT = new ClassTypeInformation(Object.class); + + private static final Map, Reference>> CACHE = Collections + .synchronizedMap(new WeakHashMap, Reference>>()); + + static { + for (TypeInformation info : Arrays.asList(COLLECTION, LIST, SET, MAP, OBJECT)) { + CACHE.put(info.getType(), new WeakReference>(info)); + } + } + private final Class type; /** @@ -39,7 +63,17 @@ public class ClassTypeInformation extends TypeDiscoverer { * @return */ public static TypeInformation from(Class type) { - return new ClassTypeInformation(type); + + Reference> cachedReference = CACHE.get(type); + TypeInformation cachedTypeInfo = cachedReference == null ? null : cachedReference.get(); + + if (cachedTypeInfo != null) { + return (TypeInformation) cachedTypeInfo; + } + + TypeInformation result = new ClassTypeInformation(type); + CACHE.put(type, new WeakReference>(result)); + return result; } /** @@ -48,7 +82,6 @@ public class ClassTypeInformation extends TypeDiscoverer { * @param method * @return */ - @SuppressWarnings({ "unchecked", "rawtypes" }) public static TypeInformation fromReturnTypeOf(Method method) { return new ClassTypeInformation(method.getDeclaringClass()).createInfo(method.getGenericReturnType()); } @@ -62,7 +95,6 @@ public class ClassTypeInformation extends TypeDiscoverer { this(type, GenericTypeResolver.getTypeVariableMap(type)); } - @SuppressWarnings("rawtypes") ClassTypeInformation(Class type, Map typeVariableMap) { super(type, typeVariableMap); this.type = type; diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java index ba4cb6daf..20348515c 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/util/ClassTypeInformationUnitTests.java @@ -148,6 +148,16 @@ public class ClassTypeInformationUnitTests { assertThat(property.getType(), is(typeCompatibleWith(byte[].class))); } + /** + * @see DATACMNS-77 + */ + @Test + public void returnsSameInstanceForCachedClass() { + + TypeInformation info = ClassTypeInformation.from(PropertyGetter.class); + assertThat(ClassTypeInformation.from(PropertyGetter.class), is(sameInstance(info))); + } + static class StringMapContainer extends MapContainer { }