天天看點

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"));

    }

}

測試結果截圖