diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
index 6838dc3779..8cbfcc6f5a 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
@@ -177,7 +177,7 @@ final class SynthesizedMergedAnnotationInvocationHandler i
private String annotationToString() {
String string = this.string;
if (string == null) {
- StringBuilder builder = new StringBuilder("@").append(this.type.getName()).append('(');
+ StringBuilder builder = new StringBuilder("@").append(getName(this.type)).append('(');
for (int i = 0; i < this.attributes.size(); i++) {
Method attribute = this.attributes.get(i);
if (i > 0) {
@@ -202,7 +202,7 @@ final class SynthesizedMergedAnnotationInvocationHandler i
return ((Enum>) value).name();
}
if (value instanceof Class) {
- return ((Class>) value).getName() + ".class";
+ return getName((Class>) value) + ".class";
}
if (value.getClass().isArray()) {
StringBuilder builder = new StringBuilder("{");
@@ -277,6 +277,11 @@ final class SynthesizedMergedAnnotationInvocationHandler i
return (A) Proxy.newProxyInstance(classLoader, interfaces, handler);
}
+ private static String getName(Class> clazz) {
+ String canonicalName = clazz.getCanonicalName();
+ return (canonicalName != null ? canonicalName : clazz.getName());
+ }
+
private static boolean isVisible(ClassLoader classLoader, Class> interfaceClass) {
if (classLoader == interfaceClass.getClassLoader()) {
diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java
index 0b92547863..a6ff5a0f07 100644
--- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java
+++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java
@@ -1887,15 +1887,22 @@ class MergedAnnotationsTests {
// Formatting common to Spring and JDK 9+
assertThat(string)
- .startsWith("@" + RequestMapping.class.getName() + "(")
- .contains("value={\"/test\"}", "path={\"/test\"}", "name=\"bar\"", "clazz=java.lang.Object.class")
+ .contains("value={\"/test\"}", "path={\"/test\"}", "name=\"bar\"")
.endsWith(")");
if (webMapping instanceof SynthesizedAnnotation) {
- assertThat(string).as("Spring uses Enum#name()").contains("method={GET, POST}");
+ assertThat(string).as("Spring formatting")
+ .startsWith("@org.springframework.core.annotation.MergedAnnotationsTests.RequestMapping(")
+ .contains("method={GET, POST}",
+ "clazz=org.springframework.core.annotation.MergedAnnotationsTests.RequestMethod.class",
+ "classes={org.springframework.core.annotation.MergedAnnotationsTests.RequestMethod.class}");
}
else {
- assertThat(string).as("JDK uses Enum#toString()").contains("method={method: get, method: post}");
+ assertThat(string).as("JDK 9-18 formatting")
+ .startsWith("@org.springframework.core.annotation.MergedAnnotationsTests$RequestMapping(")
+ .contains("method={method: get, method: post}",
+ "clazz=org.springframework.core.annotation.MergedAnnotationsTests$RequestMethod.class",
+ "classes={org.springframework.core.annotation.MergedAnnotationsTests$RequestMethod.class}");
}
}
@@ -2989,8 +2996,9 @@ class MergedAnnotationsTests {
RequestMethod[] method() default {};
- // clazz is only used for testing annotation toString() implementations
- Class> clazz() default Object.class;
+ Class> clazz() default RequestMethod.class;
+
+ Class>[] classes() default {RequestMethod.class};
}
@Retention(RetentionPolicy.RUNTIME)
diff --git a/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java b/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java
index 7ed75786f8..5c409d8804 100644
--- a/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/BootstrapUtilsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 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.
@@ -72,8 +72,8 @@ class BootstrapUtilsTests {
assertThatIllegalStateException().isThrownBy(() ->
resolveTestContextBootstrapper(bootstrapContext))
.withMessageContaining("Configuration error: found multiple declarations of @BootstrapWith")
- .withMessageContaining(FooBootstrapper.class.getName())
- .withMessageContaining(BarBootstrapper.class.getName());
+ .withMessageContaining(FooBootstrapper.class.getCanonicalName())
+ .withMessageContaining(BarBootstrapper.class.getCanonicalName());
}
@Test