DATACMNS-825 - Allow usage of composed annotations using @AliasFor.
We now resolve composed annotation values using @AliasFor within AnnotationBasedPersistentProperty and BasicPersistentEntity. Nevertheless it is up to the individual store implementation to make use of this. Original pull request: #156.
This commit is contained in:
committed by
Oliver Gierke
parent
ae96301ab0
commit
a40e247c25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2016 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.
|
||||
@@ -25,7 +25,7 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.data.annotation.AccessType;
|
||||
import org.springframework.data.annotation.AccessType.Type;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@@ -223,14 +223,15 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
continue;
|
||||
}
|
||||
|
||||
A annotation = AnnotationUtils.findAnnotation(method, annotationType);
|
||||
A annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
|
||||
|
||||
if (annotation != null) {
|
||||
return cacheAndReturn(annotationType, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
return cacheAndReturn(annotationType, field == null ? null : AnnotationUtils.getAnnotation(field, annotationType));
|
||||
return cacheAndReturn(annotationType,
|
||||
field == null ? null : AnnotatedElementUtils.findMergedAnnotation(field, annotationType));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 by the original author(s).
|
||||
* Copyright 2011-2016 by the original author(s).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
@@ -50,6 +50,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Jon Brisbin
|
||||
* @author Patryk Wasik
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implements MutablePersistentEntity<T, P> {
|
||||
|
||||
@@ -284,7 +285,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
*/
|
||||
public Object getTypeAlias() {
|
||||
|
||||
TypeAlias alias = getType().getAnnotation(TypeAlias.class);
|
||||
TypeAlias alias = AnnotatedElementUtils.findMergedAnnotation(getType(), TypeAlias.class);
|
||||
return alias == null ? null : StringUtils.hasText(alias.value()) ? alias.value() : null;
|
||||
}
|
||||
|
||||
@@ -366,7 +367,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return annotation;
|
||||
}
|
||||
|
||||
annotation = AnnotationUtils.findAnnotation(getType(), annotationType);
|
||||
annotation = AnnotatedElementUtils.findMergedAnnotation(getType(), annotationType);
|
||||
annotationCache.put(annotationType, annotation);
|
||||
|
||||
return annotation;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
* Copyright 2012-2016 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.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.util;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.FieldCallback;
|
||||
@@ -27,6 +28,7 @@ import org.springframework.util.ReflectionUtils.FieldCallback;
|
||||
* afterwards.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AnnotationDetectionFieldCallback implements FieldCallback {
|
||||
|
||||
@@ -54,7 +56,7 @@ public class AnnotationDetectionFieldCallback implements FieldCallback {
|
||||
return;
|
||||
}
|
||||
|
||||
Annotation annotation = field.getAnnotation(annotationType);
|
||||
Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(field, annotationType);
|
||||
|
||||
if (annotation != null) {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 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.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.data.util;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
* {@link MethodCallback} to find annotations of a given type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class AnnotationDetectionMethodCallback<A extends Annotation> implements MethodCallback {
|
||||
|
||||
@@ -94,7 +95,7 @@ public class AnnotationDetectionMethodCallback<A extends Annotation> implements
|
||||
return;
|
||||
}
|
||||
|
||||
A foundAnnotation = AnnotationUtils.findAnnotation(method, annotationType);
|
||||
A foundAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
|
||||
|
||||
if (foundAnnotation != null) {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2016 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.
|
||||
@@ -29,6 +29,8 @@ import javax.annotation.Nullable;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.annotation.AccessType;
|
||||
import org.springframework.data.annotation.AccessType.Type;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@@ -220,6 +222,37 @@ public class AnnotationBasedPersistentPropertyUnitTests<P extends AnnotationBase
|
||||
assertThat(field.get(MyAnnotation.class), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-825
|
||||
*/
|
||||
@Test
|
||||
public void composedAnnotationWithAliasForGetCachedCorrectly() {
|
||||
|
||||
SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");
|
||||
|
||||
// Assert direct annotations are cached on construction
|
||||
Map<Class<? extends Annotation>, Annotation> cache = getAnnotationCache(property);
|
||||
assertThat(cache.containsKey(MyComposedAnnotationUsingAliasFor.class), is(true));
|
||||
assertThat(cache.containsKey(MyAnnotation.class), is(false));
|
||||
|
||||
// Assert meta annotation is found and cached
|
||||
MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
|
||||
assertThat(annotation, is(notNullValue()));
|
||||
assertThat(cache.containsKey(MyAnnotation.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-825
|
||||
*/
|
||||
@Test
|
||||
public void composedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() {
|
||||
|
||||
SamplePersistentProperty property = entity.getPersistentProperty("metaAliased");
|
||||
|
||||
MyAnnotation annotation = property.findAnnotation(MyAnnotation.class);
|
||||
assertThat(AnnotationUtils.getValue(annotation), is((Object) "spring"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Class<? extends Annotation>, Annotation> getAnnotationCache(SamplePersistentProperty property) {
|
||||
return (Map<Class<? extends Annotation>, Annotation>) ReflectionTestUtils.getField(property, "annotationCache");
|
||||
@@ -248,6 +281,8 @@ public class AnnotationBasedPersistentPropertyUnitTests<P extends AnnotationBase
|
||||
|
||||
@MyAnnotationAsMeta String meta;
|
||||
|
||||
@MyComposedAnnotationUsingAliasFor String metaAliased;
|
||||
|
||||
@MyAnnotation
|
||||
public String getGetter() {
|
||||
return getter;
|
||||
@@ -314,6 +349,15 @@ public class AnnotationBasedPersistentPropertyUnitTests<P extends AnnotationBase
|
||||
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value = { FIELD, METHOD })
|
||||
@MyAnnotation
|
||||
public static @interface MyComposedAnnotationUsingAliasFor {
|
||||
|
||||
@AliasFor(annotation = MyAnnotation.class, attribute = "value")
|
||||
String name() default "spring";
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
|
||||
@Id
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2015 the original author or authors.
|
||||
* Copyright 2011-2016 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.
|
||||
@@ -19,6 +19,8 @@ import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -30,6 +32,7 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
@@ -224,6 +227,17 @@ public class BasicPersistentEntityUnitTests<T extends PersistentProperty<T>> {
|
||||
assertThat(entity.getPropertyAccessor(new Subtype()), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-825
|
||||
*/
|
||||
@Test
|
||||
public void returnsTypeAliasIfAnnotatedUsingComposedAnnotation() {
|
||||
|
||||
PersistentEntity<AliasEntityUsingComposedAnnotation, T> entity = createEntity(
|
||||
AliasEntityUsingComposedAnnotation.class);
|
||||
assertThat(entity.getTypeAlias(), is((Object) "bar"));
|
||||
}
|
||||
|
||||
private <S> BasicPersistentEntity<S, T> createEntity(Class<S> type) {
|
||||
return createEntity(type, null);
|
||||
}
|
||||
@@ -251,5 +265,18 @@ public class BasicPersistentEntityUnitTests<T extends PersistentProperty<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@TypeAlias("foo")
|
||||
static @interface ComposedTypeAlias {
|
||||
|
||||
@AliasFor(annotation = TypeAlias.class, attribute = "value")
|
||||
String name() default "bar";
|
||||
}
|
||||
|
||||
@ComposedTypeAlias
|
||||
static class AliasEntityUsingComposedAnnotation {
|
||||
|
||||
}
|
||||
|
||||
static class Subtype extends Entity {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user