From a3cc00d8289ac3e8043d3359f969c1862d5154d3 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 1 Jun 2016 18:17:47 +0200 Subject: [PATCH] =?UTF-8?q?DATACMNS-743=20-=20Optimizations=20in=20TypeDis?= =?UTF-8?q?coverer=20getProperty(=E2=80=A6)=20in=20case=20if=20invalid=20p?= =?UTF-8?q?roperty=20names.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now also cache a failed property lookup so that we can return null on a subsequent call for the same invalid property name right away and don't have to reattempt the lookup unnecessarily. --- .../data/util/TypeDiscoverer.java | 80 +++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/src/main/java/org/springframework/data/util/TypeDiscoverer.java index 4e09d75a6..f5abe9dab 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -36,6 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.BeanUtils; import org.springframework.core.GenericTypeResolver; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; /** @@ -47,7 +48,7 @@ class TypeDiscoverer implements TypeInformation { private final Type type; private final Map, Type> typeVariableMap; - private final Map> fieldTypes = new ConcurrentHashMap>(); + private final Map fieldTypes = new ConcurrentHashMap(); private final int hashCode; private boolean componentTypeResolved = false; @@ -188,14 +189,14 @@ class TypeDiscoverer implements TypeInformation { int separatorIndex = fieldname.indexOf('.'); if (separatorIndex == -1) { + if (fieldTypes.containsKey(fieldname)) { - return fieldTypes.get(fieldname); + return fieldTypes.get(fieldname).getType(); } TypeInformation propertyInformation = getPropertyInformation(fieldname); - if (propertyInformation != null) { - fieldTypes.put(fieldname, propertyInformation); - } + fieldTypes.put(fieldname, ValueHolder.of(propertyInformation)); + return propertyInformation; } @@ -645,4 +646,73 @@ class TypeDiscoverer implements TypeInformation { return result; } } + + /** + * Simple wrapper type to cache {@literal null} {@link TypeInformation}s. + * + * @author Oliver Gierke + */ + private static class ValueHolder { + + private static final ValueHolder NULL_HOLDER = new ValueHolder(null); + + private final TypeInformation type; + + /** + * Creates a new {@link ValueHolder} for the given {@link TypeInformation}. + * + * @param value can be {@literal null}. + */ + private ValueHolder(TypeInformation value) { + this.type = value; + } + + /** + * Returns a {@link ValueHolder} for the given {@link TypeInformation}. + * + * @param value can be {@literal null}. + * @return will never be {@literal null}. + */ + public static ValueHolder of(TypeInformation value) { + return value == null ? NULL_HOLDER : new ValueHolder(value); + } + + /** + * Returns the {@link TypeInformation} contained in the {@link ValueHolder}. + * + * @return can be {@literal null}. + */ + public TypeInformation getType() { + return type; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (obj == this) { + return true; + } + + if (!(obj instanceof ValueHolder)) { + return false; + } + + ValueHolder that = (ValueHolder) obj; + + return ObjectUtils.nullSafeEquals(this.type, that.type); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return ObjectUtils.nullSafeHashCode(type); + } + } }