注解继承:
1.被@Inherited元注解标注的注解标注在类上的时候,子类可以继承父类上的注解。
2.注解未被@Inherited元注解标注的,该注解标注在类上时,子类不会继承父类上标注的注解。
3.注解标注在接口上,其子类及子接口都不会继承该注解。
4.注解标注在类或接口方法上,其子类重写该方法不会继承父类或接口中方法上标记的注解。
注解继承分为两种情况:
- 类级别 Type (Class, Interface)
- 属性和方法级别 (Property, Method)
类级别 (Type): 注解 仅 在 类 Class 上且注解上含有 元注解 @Inherited 时, 才会被继承;(在 jdk 8 中, 接口Interface 无法继承任何Type类型注解)
属性和方法级别 (Property, Method): 注解无论何时都会被子类或子接口继承, 除非子类或子接口重写.
注解合并:
注解合并的含义:
合并注解就好比@RestController = @Controller + @ResponseBody,这就是 @AliasFor 的功劳。需要注意的是,离开 Spring 就无法使用了。
@AliasFor 有四个作用:
注释中的显式别名:
1 2 3 4 5 6 7 8 9
| public @interface ContextConfiguration { @AliasFor("locations") String[] value() default {}; @AliasFor("value") String[] locations() default {}; }
|
在@ContextConfiguration中, value和locations是彼此的显式别名。
元注释中属性的显式别名:
1 2 3 4 5 6 7
| @ContextConfiguration public @interface XmlTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xmlFiles(); }
|
在@XmlTestConfig中, xmlFiles是@ContextConfiguration中locations的显式别名。换句话说, xmlFiles覆盖了@ContextConfiguration中的locations属性。
注释中的隐式别名:
1 2 3 4 5 6 7 8 9 10 11 12
| @ContextConfiguration public @interface MyTestConfig { @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] value() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] groovyScripts() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xmlFiles() default {}; }
|
在@MyTestConfig中, value 、 groovyScripts和xmlFiles都是@ContextConfiguration中locations属性的显式元注释属性覆盖。因此,这三个属性也是彼此的隐式别名。
注释中的传递隐式别名:
1 2 3 4 5 6 7 8 9
| @MyTestConfig public @interface GroovyOrXmlTestConfig { @AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts") String[] groovy() default {}; @AliasFor(annotation = ContextConfiguration.class, attribute = "locations") String[] xml() default {}; }
|
@MyTestConfig
public @interface GroovyOrXmlTestConfig {
@AliasFor(annotation = MyTestConfig.class, attribute = “groovyScripts”)
String[] groovy() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = “locations”)
String[] xml() default {};
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| package com.sonic.annotation.combine;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AnnotatedElementUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME;
public class SynthesizedAnnotationTest {
@Target({ANNOTATION_TYPE, FIELD, TYPE}) @Retention(RUNTIME) @interface Test1 { String test1() default "test1"; }
@Target({ANNOTATION_TYPE, FIELD, TYPE}) @Retention(RUNTIME) @interface Test2 { String test2() default "test2"; }
@Target({ANNOTATION_TYPE, FIELD, TYPE}) @Retention(RUNTIME) @Test2 @interface Test3 { String test3() default "test3"; }
@Target({ANNOTATION_TYPE, FIELD, TYPE}) @Retention(RUNTIME) @Test2 @interface Test4 {
@AliasFor(annotation = Test2.class, attribute = "test2") String test4() default "test4"; }
@Test4 static class Element { }
@Test3 static class Element1 { }
public static void main(String[] args) { { Test2 test2 = AnnotatedElementUtils.getMergedAnnotation(Element.class, Test2.class); System.out.println(test2.test2()); } { Test2 test2 = AnnotatedElementUtils.getMergedAnnotation(Element1.class, Test2.class); System.out.println(test2); } } }
|
参考链接:
https://blog.csdn.net/agonie201218/article/details/125105295
https://blog.csdn.net/mayfly_hml/article/details/91070465