diff --git a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java index 17d274a82f05..369511513bb1 100644 --- a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java +++ b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileClassMetadata.java @@ -72,7 +72,7 @@ class ClassFileClassMetadata implements AnnotationMetadata { this.className = className; this.accessFlags = accessFlags; this.enclosingClassName = enclosingClassName; - this.superClassName = superClassName; + this.superClassName = (!className.endsWith(".package-info")) ? superClassName : null; this.independentInnerClass = independentInnerClass; this.interfaceNames = interfaceNames; this.memberClassNames = memberClassNames; @@ -268,18 +268,16 @@ void interfaces(Interfaces interfaces) { void nestMembers(String currentClassName, InnerClassesAttribute innerClasses) { for (InnerClassInfo classInfo : innerClasses.classes()) { String innerClassName = classInfo.innerClass().name().stringValue(); - // skip parent inner classes - if (!innerClassName.startsWith(currentClassName)) { - continue; - } - // the current class is an inner class - else if (currentClassName.equals(innerClassName)) { + if (currentClassName.equals(innerClassName)) { + // the current class is an inner class this.innerAccessFlags = classInfo.flags(); } - // collecting data about actual inner classes - else { - this.memberClassNames.add(ClassUtils.convertResourcePathToClassName(innerClassName)); - } + classInfo.outerClass().ifPresent(outerClass -> { + if (outerClass.name().stringValue().equals(currentClassName)) { + // collecting data about actual inner classes + this.memberClassNames.add(ClassUtils.convertResourcePathToClassName(innerClassName)); + } + }); } } 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 c1e2d7a78eb2..31fb6e7e3171 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 @@ -161,6 +161,12 @@ void getSuperClassNameWhenHasNoSuperClassReturnsNull() { assertThat(get(TestSubInterface.class).getSuperClassName()).isIn(null, "java.lang.Object"); } + @Test + void getSuperClassNameWhenPackageInfoReturnsNull() throws Exception { + Class packageClass = Class.forName(getClass().getPackageName() + ".package-info"); + assertThat(get(packageClass).getSuperClassName()).isNull(); + } + @Test void getInterfaceNamesWhenHasInterfacesReturnsNames() { assertThat(get(TestSubclass.class).getInterfaceNames()).containsExactly(TestInterface.class.getName()); @@ -178,6 +184,13 @@ void getMemberClassNamesWhenHasMemberClassesReturnsNames() { TestMemberClass.TestMemberClassInnerClass.class.getName(), TestMemberClass.TestMemberClassInnerInterface.class.getName()); } + @Test + void getMemberClassNamesWhenHasNestedMemberClassesReturnsOnlyFirstLevel() { + assertThat(get(TestNestedMemberClass.class).getMemberClassNames()).containsOnly( + TestNestedMemberClass.TestMemberClassInnerClassA.class.getName(), + TestNestedMemberClass.TestMemberClassInnerClassB.class.getName()); + } + @Test void getMemberClassNamesWhenHasNoMemberClassesReturnsEmptyArray() { assertThat(get(TestClass.class).getMemberClassNames()).isEmpty(); @@ -214,6 +227,22 @@ interface TestMemberClassInnerInterface { } + public static class TestNestedMemberClass { + + public static class TestMemberClassInnerClassA { + + public static class TestMemberClassInnerClassAA { + + } + + } + + public static class TestMemberClassInnerClassB { + + } + + } + } @Nested diff --git a/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java new file mode 100644 index 000000000000..1a2b01ed9b78 --- /dev/null +++ b/spring-core/src/test/java/org/springframework/core/type/classreading/DefaultAnnotationMetadataTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2025 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.core.type.classreading; + +import org.springframework.core.type.AbstractAnnotationMetadataTests; +import org.springframework.core.type.AnnotationMetadata; + +/** + * Tests for {@link SimpleAnnotationMetadata} and + * {@link SimpleAnnotationMetadataReadingVisitor} on Java < 24, + * and for the ClassFile API variant on Java >= 24. + * + * @author Phillip Webb + */ +class DefaultAnnotationMetadataTests extends AbstractAnnotationMetadataTests { + + @Override + protected AnnotationMetadata get(Class source) { + try { + return MetadataReaderFactory.create(source.getClassLoader()) + .getMetadataReader(source.getName()).getAnnotationMetadata(); + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + +} diff --git a/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java index 27b53e3de495..43e9fc848156 100644 --- a/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/classreading/SimpleAnnotationMetadataTests.java @@ -21,8 +21,7 @@ /** * Tests for {@link SimpleAnnotationMetadata} and - * {@link SimpleAnnotationMetadataReadingVisitor} on Java < 24, - * and for the ClassFile API variant on Java >= 24. + * {@link SimpleAnnotationMetadataReadingVisitor}. * * @author Phillip Webb */ @@ -31,8 +30,9 @@ class SimpleAnnotationMetadataTests extends AbstractAnnotationMetadataTests { @Override protected AnnotationMetadata get(Class source) { try { - return MetadataReaderFactory.create(source.getClassLoader()) - .getMetadataReader(source.getName()).getAnnotationMetadata(); + return new SimpleMetadataReaderFactory( + source.getClassLoader()).getMetadataReader( + source.getName()).getAnnotationMetadata(); } catch (Exception ex) { throw new IllegalStateException(ex);