Spring注解编程 之 注解合并
注解编程 之 注解合并
组合注解
Spring4.2
之后,就提供了组合注解的实现方式,就是将多个注解作用于一个注解,用一个注解就和依赖实现多个注解的功能。是作用的注解元素看上去更简洁美观,更强大之处是属性覆盖功能。
例如:Spring
的@RestController
,它将@ResponseBody
和@Controller
两个注解组合为一个,那么在Controller
类上只需加上@RestController
即可实现加两个注解才能实现的功能。
x
1
ElementType.TYPE) (
2
RetentionPolicy.RUNTIME) (
3
4
//组合Controller使其实现Bean注册
5
//组合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
annotation = Controller.class) (
15
String value() default "";
16
}
自定义注解
x
1
public class SelfAnnotationTest {
2
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
3
RetentionPolicy.RUNTIME) (
4
@interface TestOne {
5
String testOne() default "testOne";
6
}
7
8
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
9
RetentionPolicy.RUNTIME) (
10
@interface TestTwo {
11
String testTwo() default "testTwo";
12
}
13
14
15
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
16
RetentionPolicy.RUNTIME) (
17
@interface TestThree {
18
String testThree() default "testThree";
19
}
20
21
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
example.helloworld.annotation.SelfAnnotationTest$TestTwo(testTwo=testTwo) .
2
example.helloworld.annotation.SelfAnnotationTest$TestThree(testThree=testThree) .
3
4
Process finished with exit code 0
可以看出,AnnotatedElemnetUtils.getMergedAnnotation()
方法可以返回组合注解本身,及此注解上的元注解。
自定义注解合并
xxxxxxxxxx
1
21
1
2
3
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
4
RetentionPolicy.RUNTIME) (
5
@interface TestThree { // 合并 @TestOne 及 @TestTwo 注解
6
String testThree() default "testThree";
7
String testTwo(); // 自动对应 @TestTwo 中的属性
8
String testOne(); // 自动对应 @TestOne 中的属性
9
}
10
11
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
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
3
RetentionPolicy.RUNTIME) (
4
@interface TestOne {
5
String testOne1() default "testOne";
6
}
7
8
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
9
RetentionPolicy.RUNTIME) (
10
11
@interface TestTwo {
12
String testTwo2() default "testTwo";
13
}
14
15
ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE }) ({
16
RetentionPolicy.RUNTIME) (
17
18
@interface TestThree {
19
annotation = TestTwo.class, attribute = "testTwo2") (
20
String testThree() default "testThree";
21
annotation = TestOne.class, attribute = "testOne1") (
22
String testThree2() default "testThree2";
23
24
}
25
26
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
以上为三层属性覆盖,支持无限层覆盖。
Windy心梦无痕