Skip to content

Commit 32346b8

Browse files
committed
Introduce isSynthesizable in MergedAnnotation
This commit adds the ability to check if a the annotation managed by a MergedAnnotation is synthesizable. This makes it easier to register a JDK proxy hint if necessary See gh-28967
1 parent 653552a commit 32346b8

File tree

5 files changed

+55
-15
lines changed

5 files changed

+55
-15
lines changed

spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,15 @@ <T extends Annotation> MergedAnnotation<T>[] getAnnotationArray(String attribute
477477
*/
478478
<T extends Map<String, Object>> T asMap(Function<MergedAnnotation<?>, T> factory, Adapt... adaptations);
479479

480+
/**
481+
* Determine if this merged annotation is <em>synthesizable</em>.
482+
* <p>Consult the documentation for {@link #synthesize()} for an explanation
483+
* of what is considered synthesizable.
484+
* @return {@code true} if the mapped annotation is synthesizable
485+
* @since 6.0
486+
*/
487+
boolean isSynthesizable();
488+
480489
/**
481490
* Create a type-safe synthesized version of this merged annotation that can
482491
* be used directly in code.

spring-core/src/main/java/org/springframework/core/annotation/MissingMergedAnnotation.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -134,6 +134,11 @@ public <T extends Map<String, Object>> T asMap(Function<MergedAnnotation<?>, T>
134134
return factory.apply(this);
135135
}
136136

137+
@Override
138+
public boolean isSynthesizable() {
139+
return false;
140+
}
141+
137142
@Override
138143
public String toString() {
139144
return "(missing)";

spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,17 @@ private <T extends Map<String, Object>> Object adaptValueForMapOptions(Method at
319319
return value;
320320
}
321321

322+
@Override
323+
public boolean isSynthesizable() {
324+
// Is this a mapped annotation for a composed annotation, and are there
325+
// annotation attributes (mirrors) that need to be merged?
326+
if (getDistance() > 0 && this.resolvedMirrors.length > 0) {
327+
return true;
328+
}
329+
// Is the mapped annotation itself synthesizable?
330+
return this.mapping.isSynthesizable();
331+
}
332+
322333
@Override
323334
@SuppressWarnings("unchecked")
324335
protected A createSynthesizedAnnotation() {
@@ -347,22 +358,15 @@ private boolean isTargetAnnotation(@Nullable Object obj) {
347358
* Determine if the supplied annotation has not already been synthesized
348359
* <strong>and</strong> whether the mapped annotation is a composed annotation
349360
* that needs to have its attributes merged or the mapped annotation is
350-
* {@linkplain AnnotationTypeMapping#isSynthesizable() synthesizable} in general.
361+
* {@linkplain #isSynthesizable() synthesizable} in general.
351362
* @param annotation the annotation to check
352363
* @since 5.3.22
353364
*/
354365
private boolean isSynthesizable(Annotation annotation) {
355-
// Already synthesized?
356366
if (annotation instanceof SynthesizedAnnotation) {
357367
return false;
358368
}
359-
// Is this a mapped annotation for a composed annotation, and are there
360-
// annotation attributes (mirrors) that need to be merged?
361-
if (getDistance() > 0 && this.resolvedMirrors.length > 0) {
362-
return true;
363-
}
364-
// Is the mapped annotation itself synthesizable?
365-
return this.mapping.isSynthesizable();
369+
return isSynthesizable();
366370
}
367371

368372
@Override

spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,13 @@ void synthesizeWithoutAttributeAliases() throws Exception {
15041504
assertThat(synthesizedComponent.value()).isEqualTo("webController");
15051505
}
15061506

1507+
@Test
1508+
void isSynthesizableWithoutAttributeAliases() throws Exception {
1509+
Component component = WebController.class.getAnnotation(Component.class);
1510+
assertThat(component).isNotNull();
1511+
assertThat(MergedAnnotation.from(component).isSynthesizable()).isFalse();
1512+
}
1513+
15071514
@Test
15081515
void synthesizeAlreadySynthesized() throws Exception {
15091516
Method method = WebController.class.getMethod("handleMappedWithValueAttribute");
@@ -1567,10 +1574,16 @@ void synthesizeWhenUsingMergedAnnotationsFromApi() {
15671574
void synthesizeShouldNotSynthesizeNonsynthesizableAnnotationsWhenUsingMergedAnnotationsFromApi() {
15681575
MergedAnnotations mergedAnnotations = MergedAnnotations.from(SecurityConfig.class);
15691576

1570-
EnableWebSecurity enableWebSecurity = mergedAnnotations.get(EnableWebSecurity.class).synthesize();
1577+
MergedAnnotation<EnableWebSecurity> enableWebSecurityAnnotation =
1578+
mergedAnnotations.get(EnableWebSecurity.class);
1579+
assertThat(enableWebSecurityAnnotation.isSynthesizable()).isFalse();
1580+
EnableWebSecurity enableWebSecurity = enableWebSecurityAnnotation.synthesize();
15711581
assertThat(enableWebSecurity).isNotInstanceOf(SynthesizedAnnotation.class);
15721582

1573-
EnableGlobalAuthentication enableGlobalAuthentication = mergedAnnotations.get(EnableGlobalAuthentication.class).synthesize();
1583+
MergedAnnotation<EnableGlobalAuthentication> enableGlobalAuthenticationMergedAnnotation =
1584+
mergedAnnotations.get(EnableGlobalAuthentication.class);
1585+
assertThat(enableGlobalAuthenticationMergedAnnotation.isSynthesizable()).isFalse();
1586+
EnableGlobalAuthentication enableGlobalAuthentication = enableGlobalAuthenticationMergedAnnotation.synthesize();
15741587
assertThat(enableGlobalAuthentication).isNotInstanceOf(SynthesizedAnnotation.class);
15751588
}
15761589

@@ -1718,8 +1731,9 @@ private void testSynthesisWithImplicitAliases(Class<?> clazz, String expected)
17181731
ImplicitAliasesTestConfiguration config = clazz.getAnnotation(
17191732
ImplicitAliasesTestConfiguration.class);
17201733
assertThat(config).isNotNull();
1721-
ImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from(
1722-
config).synthesize();
1734+
MergedAnnotation<ImplicitAliasesTestConfiguration> mergedAnnotation = MergedAnnotation.from(config);
1735+
assertThat(mergedAnnotation.isSynthesizable()).isTrue();
1736+
ImplicitAliasesTestConfiguration synthesized = mergedAnnotation.synthesize();
17231737
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
17241738
assertThat(synthesized.value()).isEqualTo(expected);
17251739
assertThat(synthesized.location1()).isEqualTo(expected);
@@ -1746,8 +1760,11 @@ private void testSynthesisWithImplicitAliasesWithImpliedAliasNamesOmitted(
17461760
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration config = clazz.getAnnotation(
17471761
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration.class);
17481762
assertThat(config).isNotNull();
1763+
MergedAnnotation<ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration> mergedAnnotation =
1764+
MergedAnnotation.from(config);
1765+
assertThat(mergedAnnotation.isSynthesizable()).isTrue();
17491766
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration synthesized =
1750-
MergedAnnotation.from(config).synthesize();
1767+
mergedAnnotation.synthesize();
17511768
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
17521769
assertThat(synthesized.value()).isEqualTo(expected);
17531770
assertThat(synthesized.location()).isEqualTo(expected);

spring-core/src/test/java/org/springframework/core/annotation/MissingMergedAnnotationTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ void getDefaultValueReturnsEmpty() {
255255
assertThat(this.missing.getDefaultValue("value", Integer.class)).isEmpty();
256256
}
257257

258+
@Test
259+
void isSynthesizableReturnsFalse() {
260+
assertThat(this.missing.isSynthesizable()).isFalse();
261+
}
262+
258263
@Test
259264
void synthesizeThrowsNoSuchElementException() {
260265
assertThatNoSuchElementException().isThrownBy(this.missing::synthesize);

0 commit comments

Comments
 (0)