Merge branch '5.3.x'

This commit is contained in:
Sam Brannen 2022-06-28 14:24:58 +02:00
commit 1374d6d912
2 changed files with 75 additions and 8 deletions

View File

@ -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

View File

@ -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 {