@Target(ElementType.ANNOTATION_TYPE) 专用于标记可修饰其他注解的元注解,确保其仅能用于注解声明,不可混用其他ElementType,是构建组合元注解(如Spring的@Component)的基础设施。

@Target(ElementType.ANNOTATION_TYPE) 是专门用来标记“注解类型的注解”,也就是告诉编译器:这个自定义注解本身只能用在其他注解的声明上。它不用于业务逻辑,而是用于构建元注解或组合注解的基础设施层。
为什么需要 ElementType.ANNOTATION_TYPE
当你想定义一个“能修饰其他注解”的注解(比如自定义的 @MyMetaAnnotation),就必须用 @Target({ANNOTATION_TYPE}),否则编译器会拒绝你把它写在 @interface 前面。例如:
错误写法(没加 ANNOTATION_TYPE):
@Target({TYPE, METHOD})
public @interface MyMeta { }
@MyMeta // 编译报错:Cannot apply annotation @MyMeta to annotation type
正确写法:
@Target(ElementType.ANNOTATION_TYPE)
public @interface MyMeta { }
@MyMeta
public @interface Service { }
创建组合元注解的典型步骤
组合元注解本质是把多个元注解(如 @Target、@Retention)和语义注解(如 @Documented)一起封装成一个新注解,简化重复声明。关键点在于:它自身必须被 @Target(ANNOTATION_TYPE) 限定,且内部要显式复用标准元注解。
- 声明目标为 ANNOTATION_TYPE,确保只允许标注在其他注解上
- 通常搭配 @Retention(RUNTIME) 和 @Documented,保证可被反射读取、生成文档
- 内部直接写入所需元注解,不需额外逻辑——Java 会在解析时自动叠加效果
完整示例:自定义 @MyStereoAnnotation
这个注解希望同时具备 @Target(TYPE) + @Retention(RUNTIME) + @Documented 的能力,并且自己也能被其他注解使用:
立即学习“Java免费学习笔记(深入)”;
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyStereoAnnotation {
String value() default "";
}
然后定义一个业务注解并应用它:
@MyStereoAnnotation
public @interface Controller {
String value() default "";
}
此时 @Controller 就天然拥有了 TYPE 作用域、RUNTIME 生命周期和文档可见性——因为 @MyStereoAnnotation 已经把这三个元注解“注入”进来了。
注意事项
ElementType.ANNOTATION_TYPE 不可与其他 ElementType 混用(比如 {ANNOTATION_TYPE, TYPE}),否则会导致该注解既可用于注解声明、又可用于类声明,违背元注解的设计意图;
它不能替代 @Target 的业务级限制(如 METHOD 或 FIELD),那些仍需在具体业务注解中单独声明;
Spring 的 @Component、@Service 等本身就是被 @Target(ANNOTATION_TYPE) 修饰过的组合元注解,所以它们才能用在用户自定义的 @interface 上。


















