diff --git a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java index b7993a1b2..e41782663 100644 --- a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java @@ -20,8 +20,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -44,13 +44,14 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Christoph Strobl */ -public abstract class AnnotationBasedPersistentProperty

> extends - AbstractPersistentProperty

{ +public abstract class AnnotationBasedPersistentProperty

> + extends AbstractPersistentProperty

{ private static final String SPRING_DATA_PACKAGE = "org.springframework.data"; private final Value value; - private final Map, Annotation> annotationCache = new HashMap, Annotation>(); + private final Map, CachedValue> annotationCache = // + new ConcurrentHashMap, CachedValue>(); private Boolean isTransient; private boolean usePropertyAccess; @@ -93,11 +94,12 @@ public abstract class AnnotationBasedPersistentProperty

annotationType = annotation.annotationType(); - validateAnnotation(annotation, "Ambiguous mapping! Annotation %s configured " - + "multiple times on accessor methods of property %s in class %s!", annotationType.getSimpleName(), - getName(), getOwner().getType().getSimpleName()); + validateAnnotation(annotation, + "Ambiguous mapping! Annotation %s configured " + + "multiple times on accessor methods of property %s in class %s!", + annotationType.getSimpleName(), getName(), getOwner().getType().getSimpleName()); - annotationCache.put(annotationType, annotation); + cacheAndReturn(annotationType, annotation); } } @@ -109,11 +111,11 @@ public abstract class AnnotationBasedPersistentProperty

annotationType = annotation.annotationType(); - validateAnnotation(annotation, "Ambiguous mapping! Annotation %s configured " - + "on field %s and one of its accessor methods in class %s!", annotationType.getSimpleName(), - field.getName(), getOwner().getType().getSimpleName()); + validateAnnotation(annotation, + "Ambiguous mapping! Annotation %s configured " + "on field %s and one of its accessor methods in class %s!", + annotationType.getSimpleName(), field.getName(), getOwner().getType().getSimpleName()); - annotationCache.put(annotationType, annotation); + cacheAndReturn(annotationType, annotation); } } @@ -133,7 +135,9 @@ public abstract class AnnotationBasedPersistentProperty

cachedValue = annotationCache.get(annotationType); + + if (cachedValue != null && !annotationCache.get(annotationType).value.equals(candidate)) { throw new MappingException(String.format(message, arguments)); } } @@ -151,7 +155,7 @@ public abstract class AnnotationBasedPersistentProperty

cachedAnnotation = annotationCache == null ? null + : annotationCache.get(annotationType); + + if (cachedAnnotation != null) { + return (A) cachedAnnotation.getValue(); } for (Method method : Arrays.asList(getGetter(), getSetter())) { @@ -254,7 +261,7 @@ public abstract class AnnotationBasedPersistentProperty

A cacheAndReturn(Class type, A annotation) { if (annotationCache != null) { - annotationCache.put(type, annotation); + annotationCache.put(type, CachedValue.of(annotation)); } return annotation; @@ -292,12 +299,17 @@ public abstract class AnnotationBasedPersistentProperty

annotation : annotationCache.values()) { + if (annotation.value != null) { + builder.append(annotation.value.toString()).append(" "); } } return builder.toString() + super.toString(); } + + @lombok.Value(staticConstructor = "of") + static class CachedValue { + T value; + } } diff --git a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java index 4671fbdc8..bd354af6e 100644 --- a/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/AnnotationBasedPersistentPropertyUnitTests.java @@ -38,6 +38,7 @@ import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.annotation.Transient; import org.springframework.data.mapping.context.SampleMappingContext; import org.springframework.data.mapping.context.SamplePersistentProperty; +import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.CachedValue; import org.springframework.test.util.ReflectionTestUtils; /** @@ -168,7 +169,7 @@ public class AnnotationBasedPersistentPropertyUnitTests

, ?> field = (Map, ?>) ReflectionTestUtils.getField(property, "annotationCache"); assertThat(field.containsKey(MyAnnotation.class), is(true)); - assertThat(field.get(MyAnnotation.class), is(nullValue())); + assertThat(field.get(MyAnnotation.class), is((Object) CachedValue.of(null))); } @Test // DATACMNS-825