Merge branch '5.3.x'
This commit is contained in:
commit
1374d6d912
|
@ -323,11 +323,11 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected A createSynthesizedAnnotation() {
|
protected A createSynthesizedAnnotation() {
|
||||||
// Check root annotation
|
// Check root annotation
|
||||||
if (isTargetAnnotation(this.rootAttributes) && isNotSynthesizable((Annotation) this.rootAttributes)) {
|
if (isTargetAnnotation(this.rootAttributes) && !isSynthesizable((Annotation) this.rootAttributes)) {
|
||||||
return (A) this.rootAttributes;
|
return (A) this.rootAttributes;
|
||||||
}
|
}
|
||||||
// Check meta-annotation
|
// Check meta-annotation
|
||||||
else if (isTargetAnnotation(this.mapping.getAnnotation()) && isNotSynthesizable(this.mapping.getAnnotation())) {
|
else if (isTargetAnnotation(this.mapping.getAnnotation()) && !isSynthesizable(this.mapping.getAnnotation())) {
|
||||||
return (A) this.mapping.getAnnotation();
|
return (A) this.mapping.getAnnotation();
|
||||||
}
|
}
|
||||||
return SynthesizedMergedAnnotationInvocationHandler.createProxy(this, getType());
|
return SynthesizedMergedAnnotationInvocationHandler.createProxy(this, getType());
|
||||||
|
@ -344,14 +344,25 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the supplied annotation has already been synthesized or if the
|
* Determine if the supplied annotation has not already been synthesized
|
||||||
* mapped annotation is not {@linkplain AnnotationTypeMapping#isSynthesizable()
|
* <strong>and</strong> whether the mapped annotation is a composed annotation
|
||||||
* synthesizable} in general.
|
* that needs to have its attributes merged or the mapped annotation is
|
||||||
|
* {@linkplain AnnotationTypeMapping#isSynthesizable() synthesizable} in general.
|
||||||
* @param annotation the annotation to check
|
* @param annotation the annotation to check
|
||||||
* @since 5.3.22
|
* @since 5.3.22
|
||||||
*/
|
*/
|
||||||
private boolean isNotSynthesizable(Annotation annotation) {
|
private boolean isSynthesizable(Annotation annotation) {
|
||||||
return (annotation instanceof SynthesizedAnnotation || !this.mapping.isSynthesizable());
|
// Already synthesized?
|
||||||
|
if (annotation instanceof SynthesizedAnnotation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Is this a mapped annotation for a composed annotation, and are there
|
||||||
|
// annotation attributes (mirrors) that need to be merged?
|
||||||
|
if (getDistance() > 0 && this.resolvedMirrors.length > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Is the mapped annotation itself synthesizable?
|
||||||
|
return this.mapping.isSynthesizable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -1539,7 +1540,28 @@ class MergedAnnotationsTests {
|
||||||
assertThat(generatedValue).isSameAs(synthesizedGeneratedValue);
|
assertThat(generatedValue).isSameAs(synthesizedGeneratedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test // gh-28716
|
||||||
|
void synthesizeWhenUsingMergedAnnotationsFromApi() {
|
||||||
|
Field directlyAnnotatedField = ReflectionUtils.findField(DomainType.class, "directlyAnnotated");
|
||||||
|
MergedAnnotations mergedAnnotations = MergedAnnotations.from(directlyAnnotatedField);
|
||||||
|
RootAnnotation rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
|
||||||
|
assertThat(rootAnnotation.flag()).isFalse();
|
||||||
|
assertThat(rootAnnotation).isNotInstanceOf(SynthesizedAnnotation.class);
|
||||||
|
|
||||||
|
Field metaAnnotatedField = ReflectionUtils.findField(DomainType.class, "metaAnnotated");
|
||||||
|
mergedAnnotations = MergedAnnotations.from(metaAnnotatedField);
|
||||||
|
rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
|
||||||
|
assertThat(rootAnnotation.flag()).isTrue();
|
||||||
|
assertThat(rootAnnotation).isInstanceOf(SynthesizedAnnotation.class);
|
||||||
|
|
||||||
|
Field metaMetaAnnotatedField = ReflectionUtils.findField(DomainType.class, "metaMetaAnnotated");
|
||||||
|
mergedAnnotations = MergedAnnotations.from(metaMetaAnnotatedField);
|
||||||
|
rootAnnotation = mergedAnnotations.get(RootAnnotation.class).synthesize();
|
||||||
|
assertThat(rootAnnotation.flag()).isTrue();
|
||||||
|
assertThat(rootAnnotation).isInstanceOf(SynthesizedAnnotation.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // gh-28704
|
||||||
void synthesizeShouldNotSynthesizeNonsynthesizableAnnotationsWhenUsingMergedAnnotationsFromApi() {
|
void synthesizeShouldNotSynthesizeNonsynthesizableAnnotationsWhenUsingMergedAnnotationsFromApi() {
|
||||||
MergedAnnotations mergedAnnotations = MergedAnnotations.from(SecurityConfig.class);
|
MergedAnnotations mergedAnnotations = MergedAnnotations.from(SecurityConfig.class);
|
||||||
|
|
||||||
|
@ -3246,6 +3268,40 @@ class MergedAnnotationsTests {
|
||||||
static class SecurityConfig {
|
static class SecurityConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
|
||||||
|
@interface RootAnnotation {
|
||||||
|
String value() default "";
|
||||||
|
boolean flag() default false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RootAnnotation
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
|
||||||
|
@interface ComposedRootAnnotation {
|
||||||
|
|
||||||
|
@AliasFor(annotation = RootAnnotation.class, attribute = "flag")
|
||||||
|
boolean enabled() default true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@ComposedRootAnnotation
|
||||||
|
@interface DoublyComposedRootAnnotation {
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainType {
|
||||||
|
|
||||||
|
@RootAnnotation
|
||||||
|
Object directlyAnnotated;
|
||||||
|
|
||||||
|
@ComposedRootAnnotation
|
||||||
|
Object metaAnnotated;
|
||||||
|
|
||||||
|
@DoublyComposedRootAnnotation
|
||||||
|
Object metaMetaAnnotated;
|
||||||
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface TestConfiguration {
|
@interface TestConfiguration {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue