diff --git a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationMetadata.java b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationMetadata.java index abc6040873..d22ae7af6d 100644 --- a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationMetadata.java +++ b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationMetadata.java @@ -21,6 +21,7 @@ import java.lang.classfile.Annotation; import java.lang.classfile.AnnotationElement; import java.lang.classfile.AnnotationValue; import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; import java.lang.reflect.Array; import java.util.Collections; import java.util.LinkedHashMap; @@ -36,6 +37,7 @@ import org.springframework.core.annotation.AnnotationFilter; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; /** * Parse {@link RuntimeVisibleAnnotationsAttribute} into {@link MergedAnnotations} @@ -97,8 +99,9 @@ abstract class ClassFileAnnotationMetadata { } private static String fromTypeDescriptor(String descriptor) { - return descriptor.substring(1, descriptor.length() - 1) - .replace('/', '.'); + ClassDesc classDesc = ClassDesc.ofDescriptor(descriptor); + return classDesc.isPrimitive() ? "java.lang." + StringUtils.capitalize(classDesc.displayName()) : + classDesc.packageName() + "." + classDesc.displayName(); } private static Object parseArrayValue(String className, @org.jetbrains.annotations.Nullable ClassLoader classLoader, AnnotationValue.OfArray arrayValue) { diff --git a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java index 31fb6e7e31..7a990fb7f0 100644 --- a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java @@ -308,6 +308,14 @@ public abstract class AbstractAnnotationMetadataTests { assertThat(attributes.get("mv").get(0)).isEqualTo(values); } + @Test + void getAnnotationAttributeVoidType() { + MultiValueMap attributes = + get(WithVoidType.class).getAllAnnotationAttributes(ComplexAttributes.class.getName()); + assertThat(attributes).containsOnlyKeys("names", "count", "type", "subAnnotation"); + assertThat(attributes.get("type")).containsAnyOf(Void.class, void.class); + } + @Test void getRepeatableReturnsAttributes() { MultiValueMap attributes = @@ -445,12 +453,19 @@ public abstract class AbstractAnnotationMetadataTests { } + @ComplexAttributes(names = {"first", "second"}, count = TestEnum.ONE, type = TestEnum.class, subAnnotation = @SubAnnotation(name="spring")) @Metadata(mv = {42}) public static class WithComplexAttributeTypes { } + @ComplexAttributes(names = "void", count = TestEnum.ONE, type = void.class, + subAnnotation = @SubAnnotation(name="spring")) + public static class WithVoidType { + + } + @Retention(RetentionPolicy.RUNTIME) public @interface ComplexAttributes {