注解编程 之 注解合并
组合注解
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
以上为三层属性覆盖,支持无限层覆盖。