【Java 注解】自定义注解 ( 注解解析 )

举报
韩曙亮 发表于 2022/01/11 00:24:11 2022/01/11
【摘要】 文章目录 一、定义注解二、使用注解三、解析注解四、通过注解对象获取注解属性的原理 在 【Java 注解】自定义注解 ( 注解属性定义与赋值 ) 博客中讲解了 注解属性 ; 在 【J...



【Java 注解】自定义注解 ( 注解属性定义与赋值 ) 博客中讲解了 注解属性 ;

【Java 注解】自定义注解 ( 元注解 ) 博客中讲解了注解中的元注解如何描述注解 ;

本篇博客开始讲解注解在程序中如何进行 解析 和 使用 ;


注解中定义了 若干 注解属性 , 那么就需要在某个阶段 , 将 注解属性 的值拿出来 , 在某个场合让其发挥出作用 ;

解析注解 : 获取 注解属性 的值 ;





一、定义注解



定义一个注解 :

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 描述 类名, 以及类名下的方法名
 * 该注解作用于类上
 * 注解保留到运行时
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Property {
    /**
     * 注解属性 : 需要反射的类名
     * @return
     */
    String name();

    /**
     * 注解属性 : 需要反射的方法名
     * @return
     */
    int age();
}


  
 
  • 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




二、使用注解



使用上述 Property 注解 :

@Property(name = "Tom", age = 18)
public class Main {
    public static void main(String[] args) {
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5




三、解析注解



在 main 函数中解析 Main 类上的 @Property(name = "Tom", age = 18) 注解 ;


首先 , 获取该 Main 类的字节码对象 ; 在哪个类上添加了注解 , 就获取哪个类的字节码文件 ;

// 1. 获取该 Main 类的字节码对象,
//    哪个类上添加了注解 , 就获取哪个类的字节码文件
Class<Main> clazz = Main.class;

  
 
  • 1
  • 2
  • 3

然后 , 获取字节码上的注解对象 , 通过调用 getAnnotation 获取指定注解类型的对象 , 也可以调用 getAnnotations 方法 , 获取作用在该字节码类上的所有注解 ;

// 2. 获取字节码上的注解对象
Property propertyAnnotation = clazz.getAnnotation(Property.class);

  
 
  • 1
  • 2

最后 , 从注解对象中 , 获取注解属性 , 调用 注解属性 对应的抽象方法即可获取 注解属性 值 ;

// 3. 调用 注解对象 中的抽象方法, 获取其返回值
//    注解的本质就是接口, 其中的注解属性本质是 抽象方法
//    注解对象可以直接调用注解超抽象方法,
//      是因为在内存中生成了该 注解 接口的子类对象, 实现了 name 和 age 方法
// 获取注解属性 name
String name = propertyAnnotation.name();
// 获取注解属性 age
int age = propertyAnnotation.age();

System.out.println("注解属性值 : name = " + name + " , age = " + age);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

完整代码如下 :

package annotation;

@Property(name = "Tom", age = 18)
public class Main {

    public static void main(String[] args) {

        // 解析注解

        // 1. 获取该 Main 类的字节码对象,
        //    哪个类上添加了注解 , 就获取哪个类的字节码文件
        Class<Main> clazz = Main.class;

        // 2. 获取字节码上的注解对象
        Property propertyAnnotation = clazz.getAnnotation(Property.class);

        // 3. 调用 注解对象 中的抽象方法, 获取其返回值
        //    注解的本质就是接口, 其中的注解属性本质是 抽象方法
        //    注解对象可以直接调用注解超抽象方法,
        //      是因为在内存中生成了该 注解 接口的子类对象, 实现了 name 和 age 方法
        // 获取注解属性 name
        String name = propertyAnnotation.name();
        // 获取注解属性 age
        int age = propertyAnnotation.age();

        System.out.println("注解属性值 : name = " + name + " , age = " + age);
    }
}

  
 
  • 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




四、通过注解对象获取注解属性的原理



通过注解对象获取注解属性的原理 :

注解的本质就是接口, 其中的注解属性本质是 抽象方法 , 注解对象可以直接调用注解超抽象方法 , 是因为在内存中生成了该 注解 接口的子类对象, 实现了 name 和 age 方法 , 返回值就是本类注解中的 注解属性值 ;

在 Main 类上标注了 @Property(name = "Tom", age = 18) 注解 , 该 Main 类运行时 , 则在内存中生成的 注解 接口的子类对象 , 大概形式如下 :

public class PropertyImpl implements Property {
    @Override
    public String name() {
        return "Tom";
    }

    @Override
    public int age() {
        return 18;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

因此 , 通过注解属性 , 调用 name 和 age 方法 , 可以获取到注解的 注解属性 值 ;

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/116949125

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。