天天看点

Spring @AliasFor 的三种用法,亲测可用,包含测试代码

查看Spring中的@AliasFor的文档,英文描述如下:

Usage Scenarios

Explicit aliases within an annotation: within a single annotation, @AliasFor can be declared on a pair of attributes to signal that they are interchangeable aliases for each other.

Explicit alias for attribute in meta-annotation: if the annotation attribute of @AliasFor is set to a different annotation than the one that declares it, the attribute is interpreted as an alias for an attribute in a meta-annotation (i.e., an explicit meta-annotation attribute override). This enables fine-grained control over exactly which attributes are overridden within an annotation hierarchy. In fact, with @AliasFor it is even possible to declare an alias for the value attribute of a meta-annotation.

Implicit aliases within an annotation: if one or more attributes within an annotation are declared as attribute overrides for the same meta-annotation attribute (either directly or transitively), those attributes will be treated as a set of implicit aliases for each other, resulting in behavior analogous to that for explicit aliases within an annotation.

下面对每个进行理解并测试

一、Explicit aliases within an annotation

within a single annotation, @AliasFor can be declared on a pair of attributes to signal that they are interchangeable aliases for each other

意思是注解中的属性可以互相为别名进行使用

验证代码:

//定义注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface MyAliasAnnotation {

    @AliasFor(value = "location")

    String value() default "";

    @AliasFor(value = "value")

    String location() default "";

}

//编写测试类

public class MyClass {

    @MyAliasAnnotation(location = "这是值")

    public static void one(){

    }

    @MyAliasAnnotation(value = "这是值")

    public static void one2(){

    }

}

//编写测试代码

public class MyClassTest {

    @Test

    public void test1() throws NoSuchMethodException {

        Consumer<MyAliasAnnotation> logic = a -> {

            Assert.assertTrue("", "这是值".equals(a.value()));

            Assert.assertTrue("", a.value().equals(a.location()));

        };

        MyAliasAnnotation aliasAnnotation = AnnotationUtils.findAnnotation(MyClass.class.getMethod("one"), MyAliasAnnotation.class);

        logic.accept(aliasAnnotation);

        MyAliasAnnotation aliasAnnotation2 = AnnotationUtils.findAnnotation(MyClass.class.getMethod("one2"), MyAliasAnnotation.class);

        logic.accept(aliasAnnotation2);

    }

}

测试结果截图

二、Explicit alias for attribute in meta-annotation

if the annotation attribute of @AliasFor is set to a different annotation than the one that declares it, the attribute is interpreted as an alias for an attribute in a meta-annotation (i.e., an explicit meta-annotation attribute override). This enables fine-grained control over exactly which attributes are overridden within an annotation hierarchy. In fact, with @AliasFor it is even possible to declare an alias for the value attribute of a meta-annotation.

简略意思是注解中使用了元注解时,可以对元注解的值进行重写,目的是为了能达到和类继承中override相似的功能

验证代码:

//编写元注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface AnnotaionBase {

    String value() default "";

}

//编写子注解,其中子注解打上了元注解@AnnotaionBase标识

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@AnnotaionBase

public @interface AnnotationChild {

    @AliasFor(annotation = AnnotaionBase.class, attribute = "value")

    String extendValue() default "";

}

//编写测试类

@AnnotationChild(extendValue = "extendValue")

public class ExtendClass {

}

//编写测试代码

public class ExtendAnnotationTest {

    @Test

    public void test() throws NoSuchMethodException {

        AnnotaionBase annotaionBase = AnnotatedElementUtils.findMergedAnnotation(ExtendClass.class, AnnotaionBase.class);

        Assert.assertTrue("", annotaionBase.value().equals("extendValue"));

    }

}

测试结果截图

其中要注意的是这里要使用AnnotatedElementUtils,如果还是用AnnotationUtils会发现继承不起作用,这个在AnnotationUtils类的英文文档中也有说明:

在这里也说明了看文档的重要性,往往很多坑在文档里会有特别说明

三、Implicit aliases within an annotation

if one or more attributes within an annotation are declared as attribute overrides for the same meta-annotation attribute (either directly or transitively), those attributes will be treated as a set of implicit aliases for each other, resulting in behavior analogous to that for explicit aliases within an annotation.

简略意思是注解中使用了元注解时,可以对元注解的值进行重写,并且可用多个不同的别名进行重写(其实就是一和二的结合)

验证代码:

//编写元注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface AnnotaionBase {

    String value() default "";

}

//编写子注解,其中子注解打上了元注解@AnnotaionBase标识

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@AnnotaionBase

public @interface AnnotationChildMutilAttribute {

    @AliasFor(annotation = AnnotaionBase.class, attribute = "value")

    String extendValue1() default "";

    @AliasFor(annotation = AnnotaionBase.class, attribute = "value")

    String extendValue2() default "";

}

//编写测试类

public class ExtendMutilClass {

    @AnnotationChildMutilAttribute(extendValue1 = "extendValue1")

    public static class extendValue1{

    }

    @AnnotationChildMutilAttribute(extendValue2 = "extendValue2")

    public static class extendValue2{

    }

}

//编写测试代码

public class ExtendAnnotaionMutilAttributeTest {

    @Test

    public void test(){

        AnnotationChildMutilAttribute mergedAnnotation1 = AnnotatedElementUtils.findMergedAnnotation(ExtendMutilClass.extendValue1.class, AnnotationChildMutilAttribute.class);

        Assert.assertTrue(mergedAnnotation1.extendValue1().equals("extendValue1"));

        Assert.assertTrue(mergedAnnotation1.extendValue2().equals("extendValue1"));

        AnnotationChildMutilAttribute mergedAnnotation2 = AnnotatedElementUtils.findMergedAnnotation(ExtendMutilClass.extendValue2.class, AnnotationChildMutilAttribute.class);

        Assert.assertTrue(mergedAnnotation2.extendValue1().equals("extendValue2"));

        Assert.assertTrue(mergedAnnotation2.extendValue2().equals("extendValue2"));

    }

}

测试结果截图