I’m using SpringBoot 2.4.2. And I’m struggling with @AliasFor with custom annotation.
I implemented below custom annotation.
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CustomAnnotation { @AliasFor("aliasAttribute") String value() default ""; @AliasFor("value") String aliasAttribute() ""; }
And using it like this.
@CustomAnnoatation("test") @Component public class TestClass() { // codes here }
And this test code fails.
@SpringBootTest(classes = TestClass.class) public class CustomAnnotationTest { @Autowired TestClass testClass; @Test public void valueTest1() { Annotation annotation = testClass.getClass().getAnnotation(CustomAnnotation.class); assertThat(((CustomAnnotation) annotation).value()).isEqualTo(((CustomAnnotation) annotation).aliasAttribute()); } }
with message
org.opentest4j.AssertionFailedError: Expecting: <""> to be equal to: <"test">
I don’t know why, anyone know?
Advertisement
Answer
An annotation is static metadata for a class, field etc. so Spring cannot change anything about it. To make features as @AliasFor
possible Spring uses, what they call, synthesized annotations. For those to be used/detected you need to utilize the Spring internals to obtain that synthesized annotation and for the @AliasFor
to work. For this use AnnotationUtils.findAnnotation
(Spring uses that internally as well).
@AliasFor
is a Spring feature so without using the Spring components this won’t work.
Your test method is basically the same as
@Test public void valueTest1() { Annotation annotation = TestClass.class.getAnnotation(CustomAnnotation.class); assertThat(((CustomAnnotation) annotation).value()).isEqualTo(((CustomAnnotation) annotation).aliasAttribute()); }
Both this test and your test will fail, because they simply don’t use the Spring infrastructure for detecting annotations and apply the features of Spring.
When using AnnotationUtils.findAnnotation
the test will pass.
class CustomAnnotationTest { @Test void testStandardJava() { CustomAnnotation annotation = TestClass.class.getAnnotation(CustomAnnotation.class); assertThat(annotation.value()).isEqualTo(annotation.aliasAttribute()); } @Test void testWithSpring() { CustomAnnotation annotation = AnnotationUtils.findAnnotation(TestClass.class, CustomAnnotation.class); assertThat(annotation.value()).isEqualTo(annotation.aliasAttribute()); } }
The testStandardJava
will fail, the testWithSpring
will pass because it uses the proper mechanisms.