Spring注解编程 之 注解合并


注解编程 之 注解合并

组合注解

Spring4.2之后,就提供了组合注解的实现方式,就是将多个注解作用于一个注解,用一个注解就和依赖实现多个注解的功能。是作用的注解元素看上去更简洁美观,更强大之处是属性覆盖功能。

例如:Spring@RestController,它将@ResponseBody@Controller两个注解组合为一个,那么在Controller类上只需加上@RestController即可实现加两个注解才能实现的功能。

     
x
        1
@Target(ElementType.TYPE)
2
@Retention(RetentionPolicy.RUNTIME)
3
@Documented
4
@Controller  //组合Controller使其实现Bean注册
5
@ResponseBody  //组合ResponseBody使其支持将结果转化为json
6
public @interface RestController {
7




8

    /**
9
     * The value may indicate a suggestion for a logical component name,
10
     * to be turned into a Spring bean in case of an autodetected component.
11
     * @return the suggested component name, if any (or empty String otherwise)
12
     * @since 4.0.1
13
     */
14
    @AliasFor(annotation = Controller.class)
15
    String value() default "";
16
}
   

自定义注解

     
x
        1
public class SelfAnnotationTest {
2
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
3
    @Retention(RetentionPolicy.RUNTIME)
4
    @interface TestOne {
5
        String testOne() default "testOne";
6
    }
7
?
8
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
9
    @Retention(RetentionPolicy.RUNTIME)
10
    @interface TestTwo {
11
        String testTwo() default "testTwo";
12
    }
13
?
14
    @TestTwo
15
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
16
    @Retention(RetentionPolicy.RUNTIME)
17
    @interface TestThree {
18
        String testThree() default "testThree";
19
    }
20
?
21
    @TestThree
22
    static class Element {}
23
?
24
    public static void main(String[] args) {
25
        TestTwo testTwo = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestTwo.class);
26
        TestThree testThree = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestThree.class);
27
        System.out.println(testTwo);
28
        System.out.println(testThree);
29
    }
30
}
   

输出:

     
x
        1
@com.example.helloworld.annotation.SelfAnnotationTest$TestTwo(testTwo=testTwo)
2
@com.example.helloworld.annotation.SelfAnnotationTest$TestThree(testThree=testThree)
3
?
4
Process finished with exit code 0
   

可以看出,AnnotatedElemnetUtils.getMergedAnnotation()方法可以返回组合注解本身,及此注解上的元注解。

自定义注解合并

     
xxxxxxxxxx
1 21         1
    @TestOne
2
    @TestTwo
3
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
4
    @Retention(RetentionPolicy.RUNTIME)
5
    @interface TestThree { // 合并 @TestOne 及 @TestTwo 注解
6
        String testThree() default "testThree";
7
        String testTwo();  // 自动对应 @TestTwo 中的属性
8
        String testOne();  // 自动对应 @TestOne 中的属性
9
    }
10
?
11
    @TestThree(testTwo = "test2", testOne = "test1")
12
    static class Element {}
13
?
14
    public static void main(String[] args) {
15
        TestTwo testTwo = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestTwo.class);
16
        System.out.println(testTwo.testTwo());
17
        TestThree testThree = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestThree.class);
18
        System.out.println(testThree.testThree());
19
        TestOne testOne = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestOne.class);
20
        System.out.println(testOne.testOne());
21
    }
   

输出:

     
xxxxxxxxxx
1         1
test2
2
testThree
3
test1
4
?
5
Process finished with exit code 0
   

组合注解实现属性值覆盖

Spring组合注解中的属性覆盖功能,即更底层的注解属性方法覆盖高层次注解的属性方法。实现该功能需要Spring提供的另外一个注解@AliasFor配合完成。

     
x
        1
public class SelfAnnotationTest {
2
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
3
    @Retention(RetentionPolicy.RUNTIME)
4
    @interface TestOne {
5
        String testOne1() default "testOne";
6
    }
7
?
8
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
9
    @Retention(RetentionPolicy.RUNTIME)
10
    @TestOne
11
    @interface TestTwo {
12
        String testTwo2() default "testTwo";
13
    }
14
?
15
    @Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE })
16
    @Retention(RetentionPolicy.RUNTIME)
17
    @TestTwo
18
    @interface TestThree {
19
        @AliasFor(annotation = TestTwo.class, attribute = "testTwo2")
20
        String testThree() default "testThree";
21
        @AliasFor(annotation = TestOne.class, attribute = "testOne1")
22
        String testThree2() default "testThree2";
23
?
24
    }
25
?
26
    @TestThree(testThree = "testThree 覆盖了 testTwo2", testThree2 = "testThree2 覆盖了 testOne1")
27
    static class Element {}
28
?
29
    public static void main(String[] args) {
30
        TestTwo testTwo = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestTwo.class);
31
        System.out.println(testTwo.testTwo2());
32
        TestOne testOne = AnnotatedElementUtils.getMergedAnnotation(Element.class, TestOne.class);
33
        System.out.println(testOne.testOne1());
34
    }
35
}
   

输出:

     
x
        1
testThree 覆盖了 testTwo2
2
testThree2 覆盖了 testOne1
3
?
4
Process finished with exit code 0
   

以上为三层属性覆盖,支持无限层覆盖。