Java获取类或方法上的注解

Java 获取类或方法上的注解

获取方法

Class

  • Class.getAnnotations() 获取所有的注解,包括自己声明的以及继承的
  • Class.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的
  • Class.getDeclaredAnnotations() 获取自己声明的注解

Method

  • Method.getAnnotations() 获取所有的注解,包括自己声明的以及继承的
  • Method.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的
  • Method.getDeclaredAnnotations() 获取自己声明的注解

示例

//自定义注解A
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface A {
    String value() default "";
}

//自定义注解B
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface B {
    String value() default "";
}

//使用注解
@A("testClass")
public class TestService {

    @B("testMethod")
    public void sayHello() {
        System.out.println("hello word");
    }

}

//获取
public static void main(String[] args) throws NoSuchMethodException {

    Class<?> clazz = TestService.class;
    System.out.println(Arrays.toString(clazz.getAnnotations()));
    System.out.println(clazz.getAnnotation(A.class));
    System.out.println(Arrays.toString(clazz.getDeclaredAnnotations()));

    System.out.println();

    Method method = clazz.getMethod("sayHello", null);
    System.out.println(Arrays.toString(method.getAnnotations()));
    System.out.println(method.getAnnotation(B.class));
    System.out.println(Arrays.toString(method.getDeclaredAnnotations()));

}

注意

  • 注解只有被定义为 @Inherited 才可以被子类继承
  • 当前类或方法没有被任何注解标注时,getAnnotations()getDeclaredAnnotations()返回空数组
  • 方法 getAnnotation(Class< A > annotationType) 查询的注解不存在是会返回 null
  • 子类重写了父类的方法,注解无法被继承

获取不到注解信息

自定义注解

检查注解定义:

当注解未定义 @Retention(value = RetentionPolicy.RUNTIME) 时,无法获取到注解信息。

Annotation 类型可以被它们自己所标注。Java5.0 定义了4个标准的 meta-annotation 类型,分别是:TargetRetentionDocumentedInherited,它们被用来提供对其它 annotation 类型作说明。 这些类型和它们所支持的类在 java.lang.annotation 包中可以找到。

  • @Target 的用法:指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。
    • ElementType.ANNOTATION_TYPE 应用于注释类型声明
    • ElementType.CONSTRUCTOR 构造方法声明
    • ElementType.FIELD 应用于字段声明(包括枚举常量)
    • ElementType.LOCAL_VARIABLE 应用于局部变量声明
    • ElementType.METHOD 应用于方法声明
    • ElementType.PACKAGE 应用于包声明
    • ElementType.PARAMETER 应用于参数声明
    • ElementType.TYPE 应用于类、接口(包括注释类型)或枚举声明
  • @Retention 的用法:指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS
    • RetentionPolicy.CLASS 编译器将把注释记录在类文件中,但在运行时 JVM 不需要保留注释
    • RetentionPolicy.RUNTIME 编译器将把注释记录在类文件中,在运行时 JVM 将保留注释,因此可以反射性地读取
    • RetentionPolicy.SOURCE 编译器要丢弃的注释
  • @Documented 的用法:指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。Documented 是一个没有成员的注释。
  • @Inherited 的用法:指示注释类型自动被子类继承。 Inherited 也是一个没有成员的注释

注意,如果使用 @Inherited 注释类以外的任何事物都是无效的。还要注意,此元注释仅对从超类继承注释有效;对已实现接口的注释无效。

类被代理

当前类被代理时是获取不到注解信息的,那该如何获取注解信息呢?

正常情况下我们的类是 com.spc.job.canal.CanalHandler 这样的,但是如果被 AOP 代理过的类是 class com.spc.job.canal.CanalHandler$$EnhancerBySpringCGLIB$$5770166e

解决方式一

重新获取一个没有被代理的 Class 对象:

Class<?> clazz = bean.getClass();
String name = clazz.getName();
if (name.contains("$$EnhancerBySpringCGLIB") || name.contains("$$5770166e")) {
    name = name.substring(0, name.indexOf("$$"));
}
try {
    clazz = Class.forName(name);
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e.getMessage());
}
System.out.println(Arrays.toString(clazz.getAnnotations()));

for (Method method : clazz.getMethods()) {
    System.out.println(Arrays.toString(method.getAnnotations()));
}
解决方式二

使用 Spring 里面提供的 AnnotationUtils 来读取注解

//A 为注解信息
A a = AnnotationUtils.findAnnotation(method, A.class);
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值