JAVA注解 | 组合注解的用法

如何自定义组合注解

在自定义注解时,需要为注解声明两个很重要的元注解:

  • @Retention:声明注解的生命周期
  • @Target:声明可以注解在哪些元素之上

自定义注解 @Retention 基本都是设置为 RetentionPolicy.RUNTIME,表明注解可以保留到运行期间。而 @Target 则可以选择多个元素。

元素说明
ElementType.TYPE注解在类、接口、枚举上
ElementType.FIELD注解在类中的字段上
ElementType.METHOD注解在类中的方法上
ElementType.PARAMETER注解在方法的参数前
ElementType.CONSTRUCTOR注解在类中构造方法上
ElementType.LOCAL_VARIABLE注解在局部变量前
ElementType.ANNOTATION_TYPE注解在注解上
ElementType.PACKAGE注解在包名前

@Target 设置为 ElementType.ANNOTATION_TYPE 时,则表示当前注解可以声明在其它注解之上,这就是组合注解。

接下来通过代码演示如何自定义一个组合注解:

1、自定义一个注解 AnnoA,设置 @TargetElementType.ANNOTATION_TYPE

@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AnnoA {

    String value();

}

2、自定义另外一个注解 AnnoB,在注解上声明 @AnnoA,形成组合注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AnnoA("A")
public @interface AnnoB {

    String value();

}

3、组合注解的使用与普通注解的使用是一样的

@AnnoB("B")
public class TestBean {
}

通过反射解析组合注解

既然组合注解的使用与普通注解是一样的,那是否也可以像解析普通注解一样通过反射解析组合注解呢?

public class AnnotationTest {

    public static void main(String[] args) throws Exception {
        Annotation[] annotations = TestBean.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }

}

输出结果如下,可以看到通过反射只能获取到当前类上的那个注解 AnnoB,而并不能获取到注解上的注解 AnnoA

@test.annotation.AnnoB(value=B)

如果获取不到组合注解中所有的注解,那岂不是就失去了组合的威力?JDK 的原生 API 确实不能直接获取到注解上的注解,但是通过注解然后再去获取注解还是可以完整地获取组合中所有的注解的,只是过程曲折一点。

需要注意的是:必须使用 annotationType() 方法获取 annotation 的类型才能解析注解,通过 getClass() 方法获取类型是解析不了的。

public class AnnotationTest {

    public static void main(String[] args) throws Exception {
        Annotation[] annotations = TestBean.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
            System.out.println("-----------");
            Arrays.stream(annotation.annotationType().getAnnotations())
                    .forEach(System.out::println);
        }
    }

}

输出如下,可以看出不光输出的组合的注解,还把其它几个 JDK 自带的元注解也都解析出来了,所以如果自己写工具类去处理组合注解的话,还得把这几个元注解过滤一下。

@test.annotation.AnnoB(value=B)
-----------
@java.lang.annotation.Target(value=[TYPE])
@java.lang.annotation.Retention(value=RUNTIME)
@java.lang.annotation.Documented()
@java.lang.annotation.Inherited()
@test.annotation.AnnoA(value=A)

使用 Spring 提供的工具类解析组合注解

Springspring-core 中的 org.springframework.core.annotation 包提供了大量关于注解的工具类。使用其中的 AnnotatedElementUtils 工具类就可以方便地获取组合注解中的每一个注解。

public class AnnotationTest {

    public static void main(String[] args) throws Exception {
        AnnoA annotationA = AnnotatedElementUtils.getMergedAnnotation(TestBean.class, AnnoA.class);
        System.out.println(annotationA);

        AnnoB annotationB = AnnotatedElementUtils.getMergedAnnotation(TestBean.class, AnnoB.class);
        System.out.println(annotationB);
    }

}

对于 Spring 工具类的使用,本文点到即止,后续会单独介绍如何使用及源码分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值