在JAVA1.5新特性描述里有这样一句话
Annotation type declarations cannot be generic. (Annotation types implicitly extend annotation.Annotation.) 这表明了注解类(这里说的是 @interface类,不是被注解标注的那种普通类)之间不能有继承关系,在编译阶段注解类之间的继承是不被允许的(如下图);
如果我想共用一些注解的属性怎么办呢,毕竟继承带来的复用和代码量减少都是很可观的;在Spring中则利用元注解“巧妙地”实现了这一特性。
元注解
能够标记在注解上的注解被称为元注解,比如JAVA提供的最基础的元注解
Spring则巧妙的运用了元注解代替了“父类”的角色,实现了注解的“派生”(《Spring boot编程思想 核心篇》里小马哥是这样定义的),这样的注解可以称之为“组合注解”;
Spring中有一个最最重要的元注解,也是大家最熟悉的 @Component ,这个注解在Spring框架中派生出很多组合注解如:
@Controller @Service @Repository 等
Spring中封装了一系列的组合注解相关的api,主要有 AnnotationUtils、AnnotatedElementUtils,这些api在org.springframework.core.annotation这个路径下面,有兴趣的可以一起研究研究
这里也看到了上一篇文章所AliasFor标签了
简单例子
跟上一篇文章一样,我们定义两个注解,并将一个注解当作元注解标注在另一个注解上
元注解:
package com.uu.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
String name() default "";
}
目标注解:
package com.uu.annotation;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@MyAnnotation(name = "zzz")
public @interface DemoAnnotation {
String name1() default "";
}
测试代码:
package com.uu;
import com.uu.annotation.DemoAnnotation;
import com.uu.annotation.MyAnnotation;
import org.junit.Test;
import org.springframework.core.annotation.AnnotatedElementUtils;
@DemoAnnotation(name1 = "9991")
public class DemoTest {
@Test
public void test(){
MyAnnotation bb = AnnotatedElementUtils.getMergedAnnotation(DemoTest.class, MyAnnotation.class);
System.out.println(bb);
}
}
测试打印结果:
虽然我们没有在测试类上标注 @MyAnnotation,但是我们还是通过@DemoAnnotation获得了其相关信息;Spring中这种使用常用太常见。