Skip to content

AnnotationMetadata.getAnnotationAttributes inconsistency for empty array in ASM implementation [SPR-17347] #21881

Closed
@spring-projects-issues

Description

@spring-projects-issues

LutherWest opened SPR-17347 and commented

Different implementations of AnnotationMetadata provides different annotation attributes. Currently, it makes ImportBeanDefinitionRegistrar inconsistent due to provided AnnotationMetadata in registerBeanDefinitions(...) method.

 

For the test case below, StandardAnnotationMetadata will return an empty String array (as expected). But AnnotationMetadataReadingVisitor will return Hello world!.

 

Please, consider the following test case:

@SpringBootTest(classes = ClassAnnotationMetadataTest.class)
@ClassAnnotationMetadataTest.SimpleAnnotation(arrayProperty = {}) // force emptiness
@RunWith(SpringRunner.class)
public class ClassAnnotationMetadataTest {

    @Autowired
    private ResourceLoader resourceLoader;

    private MetadataReaderFactory metadataReaderFactory;

    @Before
    public void setup() {
        this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
    }

    @Test
    public void annotationMetadataResultInconsistency() throws IOException {
        AnnotationMetadata meta1 = new StandardAnnotationMetadata(ClassAnnotationMetadataTest.class);
        AnnotationMetadata meta2 = metadataReaderFactory.getMetadataReader(ClassAnnotationMetadataTest.class.getName())
                .getAnnotationMetadata();

        Assertions.assertThat(meta1)
                .isInstanceOf(StandardAnnotationMetadata.class)
                .extracting(meta -> meta.getAnnotationAttributes(SimpleAnnotation.class.getName()))
                .containsAnyOf(entry("arrayProperty", new String[]{ }));
        Assertions.assertThat(meta2)
                .isInstanceOf(AnnotationMetadataReadingVisitor.class)
                .extracting(meta -> meta.getAnnotationAttributes(SimpleAnnotation.class.getName()))
                .containsAnyOf(entry("arrayProperty", new String[]{ }));
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface SimpleAnnotation {
        String[] arrayProperty() default "Hello world!";
    }
}

 

A bit more details, which I can found:

https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationAttributesVisitor.java#L46

This line will trigger registration of default values for annotation.

For given test case, explicitly specified empty array will be treated as absence of value (associated AnnotationAttributes object won't contain 'arrayProperty' value) and default one will be picked up.

 

Finally

Is it expected behavior?


Affects: 5.0.7

Issue Links:

Referenced from: commits 5343076, 83909e6

Backported to: 5.0.10

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions