|
17 | 17 | package org.springframework.core.convert;
|
18 | 18 |
|
19 | 19 | import java.lang.annotation.Annotation;
|
| 20 | +import java.lang.reflect.AnnotatedElement; |
20 | 21 | import java.lang.reflect.Field;
|
21 | 22 | import java.lang.reflect.Method;
|
22 | 23 | import java.util.LinkedHashMap;
|
23 | 24 | import java.util.Map;
|
24 | 25 |
|
25 | 26 | import org.springframework.core.GenericTypeResolver;
|
26 | 27 | import org.springframework.core.MethodParameter;
|
| 28 | +import org.springframework.util.ConcurrentReferenceHashMap; |
| 29 | +import org.springframework.util.ObjectUtils; |
27 | 30 | import org.springframework.util.ReflectionUtils;
|
28 | 31 | import org.springframework.util.StringUtils;
|
29 | 32 |
|
|
44 | 47 | */
|
45 | 48 | public final class Property {
|
46 | 49 |
|
| 50 | + private static Map<Property, Annotation[]> annotationCache = |
| 51 | + new ConcurrentReferenceHashMap<Property, Annotation[]>(); |
| 52 | + |
47 | 53 | private final Class<?> objectType;
|
48 | 54 |
|
49 | 55 | private final Method readMethod;
|
@@ -112,6 +118,9 @@ MethodParameter getMethodParameter() {
|
112 | 118 | }
|
113 | 119 |
|
114 | 120 | Annotation[] getAnnotations() {
|
| 121 | + if(this.annotations == null) { |
| 122 | + this.annotations = resolveAnnotations(); |
| 123 | + } |
115 | 124 | return this.annotations;
|
116 | 125 | }
|
117 | 126 |
|
@@ -182,26 +191,26 @@ private MethodParameter resolveParameterType(MethodParameter parameter) {
|
182 | 191 | }
|
183 | 192 |
|
184 | 193 | private Annotation[] resolveAnnotations() {
|
185 |
| - Map<Class<?>, Annotation> annMap = new LinkedHashMap<Class<?>, Annotation>(); |
186 |
| - Method readMethod = getReadMethod(); |
187 |
| - if (readMethod != null) { |
188 |
| - for (Annotation ann : readMethod.getAnnotations()) { |
189 |
| - annMap.put(ann.annotationType(), ann); |
190 |
| - } |
| 194 | + Annotation[] annotations = annotationCache.get(this); |
| 195 | + if(annotations == null) { |
| 196 | + Map<Class<? extends Annotation>, Annotation> annotationMap = new LinkedHashMap<Class<? extends Annotation>, Annotation>(); |
| 197 | + addAnnotationsToMap(annotationMap, getReadMethod()); |
| 198 | + addAnnotationsToMap(annotationMap, getWriteMethod()); |
| 199 | + addAnnotationsToMap(annotationMap, getField()); |
| 200 | + annotations = annotationMap.values().toArray(new Annotation[annotationMap.size()]); |
| 201 | + annotationCache.put(this, annotations); |
191 | 202 | }
|
192 |
| - Method writeMethod = getWriteMethod(); |
193 |
| - if (writeMethod != null) { |
194 |
| - for (Annotation ann : writeMethod.getAnnotations()) { |
195 |
| - annMap.put(ann.annotationType(), ann); |
196 |
| - } |
197 |
| - } |
198 |
| - Field field = getField(); |
199 |
| - if (field != null) { |
200 |
| - for (Annotation ann : field.getAnnotations()) { |
201 |
| - annMap.put(ann.annotationType(), ann); |
| 203 | + return annotations; |
| 204 | + } |
| 205 | + |
| 206 | + private void addAnnotationsToMap( |
| 207 | + Map<Class<? extends Annotation>, Annotation> annotationMap, |
| 208 | + AnnotatedElement object) { |
| 209 | + if (object != null) { |
| 210 | + for (Annotation annotation : object.getAnnotations()) { |
| 211 | + annotationMap.put(annotation.annotationType(), annotation); |
202 | 212 | }
|
203 | 213 | }
|
204 |
| - return annMap.values().toArray(new Annotation[annMap.size()]); |
205 | 214 | }
|
206 | 215 |
|
207 | 216 | private Field getField() {
|
@@ -232,4 +241,34 @@ private Class<?> declaringClass() {
|
232 | 241 | }
|
233 | 242 | }
|
234 | 243 |
|
| 244 | + @Override |
| 245 | + public int hashCode() { |
| 246 | + final int prime = 31; |
| 247 | + int hashCode = 1; |
| 248 | + hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(objectType); |
| 249 | + hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(readMethod); |
| 250 | + hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(writeMethod); |
| 251 | + hashCode = prime * hashCode + ObjectUtils.nullSafeHashCode(name); |
| 252 | + return hashCode; |
| 253 | + } |
| 254 | + |
| 255 | + @Override |
| 256 | + public boolean equals(Object obj) { |
| 257 | + if (this == obj) { |
| 258 | + return true; |
| 259 | + } |
| 260 | + if (obj == null) { |
| 261 | + return false; |
| 262 | + } |
| 263 | + if (getClass() != obj.getClass()) { |
| 264 | + return false; |
| 265 | + } |
| 266 | + Property other = (Property) obj; |
| 267 | + boolean equals = true; |
| 268 | + equals &= ObjectUtils.nullSafeEquals(objectType, other.objectType); |
| 269 | + equals &= ObjectUtils.nullSafeEquals(readMethod, other.readMethod); |
| 270 | + equals &= ObjectUtils.nullSafeEquals(writeMethod, other.writeMethod); |
| 271 | + equals &= ObjectUtils.nullSafeEquals(name, other.name); |
| 272 | + return equals; |
| 273 | + } |
235 | 274 | }
|
0 commit comments