java自定义注解怎么实现注解(怎么获取自定义注解内的值)

TL;DRJava注解广泛运用在开发之中,用于增强变量/方法/类等。尝试说明Java自定义注解的使用,以及通过开源项目中的使用进行说明。本文主要记录个人的理解,全文基于JavaSE8。自定义注解自定义注解分为两个部分:注解声明和注解处理逻辑。每个注解可以有多个属性值,同名注解通过声明后可以在对象上使用多个。注解结构定义注解用以下实例说明:12345678910@Repeatable(Lea…

大家好,又见面了,我是你们的朋友全栈君。

TL;DR

Java 注解广泛运用在开发之中,用于增强变量/方法/类等。

尝试说明 Java 自定义注解的使用,以及通过开源项目中的使用进行说明。

本文主要记录个人的理解,全文基于Java SE8。

自定义注解

自定义注解分为两个部分:注解声明和注解处理逻辑。

每个注解可以有多个属性值,同名注解通过声明后可以在对象上使用多个。

注解结构

定义注解

用以下实例说明:

1

2

3

4

5

6

7

8

9

10@Repeatable(LearnRepeatableAnnotation.class)

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD})

public @interface LearnAnnotation {

String value() default “”;

String filedAnnotationValue() default “”;

Class> className() default Void.class;

}

逐行分析一下。

@Repeatable(LearnRepeatableAnnotation.class) 表示本注解可以在一个对象上使用多次,具体内容下文会具体说明。

@Retention(RetentionPolicy.RUNTIME) 是一个元注解,表示注解可以在运行时通过反射使用,元注解下文会具体说明。

@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD}) 也是一个元注解,表示注解可以在属性、本地变量、方法上。

public @interface LearnAnnotation 表示这是一个注解声明,注解需要以@interface声明。

String value() default “”; 表示注解的值域是字符串类型,默认为空字符串。注解使用时,可以通过属性名=值的形式进行赋值,如果不声明属性名,说明会赋值到value属性上。注解中的属性名就是声明中的方法名。

String filedAnnotationValue() default “”; 表示自定义注解@LearnAnnotation有一个名为filedAnnotationValue的字符串属性,使用时可以通过@LearnAnnotation(filedAnnotationValue = “NAME”)这一形式使用。

Class> className() default Void.class; 表示自定义注解@LearnAnnotation有一个名为className的Class对象,此处需要注意,自定义注解的属性值只能是基本类型(short/int/long/boolean/char/String/enum/Class等)以及他们这些类型的数组。

注解如果没有default声明的,需要指定属性值后才能使用。

同一对象使用多个相同的注解声明

还是使用上述案例,第一行@Repeatable(LearnRepeatableAnnotation.class)通过声明利用@LearnRepeatableAnnotation这一注解表示可以在一个对象上使用多个LearnAnnotation注解。

@LearnRepeatableAnnotation 的实现如下:

1

2

3

4

5@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD})

public @interface LearnRepeatableAnnotation {

LearnAnnotation[] value() default {};

}

即需要声明一个新类型的注解,且这一注解的值,是计划使用多个注解的数组。

实际使用中可以像如下形式使用:

1

2

3@LearnAnnotation(filedAnnotationValue = “v1”)

@LearnAnnotation(value = “v2”)

private int testRepeatInt = 0;

使用多个同名注解,例如作为配置规则,可以让当前对象获取多个规则。

注解声明

注解声明又主要分为两个部分:元注解注解名称及字段定义。

元注解

Java 中提供了4种元注解:

@Documented – 在JavaDoc中提供注解信息

@Retention – 注解的生效范围

@Target – 注解允许使用的对象

@Inherited – 注解是否可以被子类继承

元注解是实现自定义注解的重要工具,最重要的是@Retention与@Target。

元注解@Retention

元注解 @Retention 可以有如下3个属性值:

RetentionPolicy.SOURCE – 注解保留在源码中,编译阶段会被丢弃

RetentionPolicy.CLASS – 注解保留在.class文件中,但不会在运行时存在

RetentionPolicy.RUNTIME – 注解可以在运行时读取、使用反射可以获得

默认是RetentionPolicy.CLASS。

在注解指定了 RetentionPolicy.SOURCE 的情况下,Java 编译源码时,会有一个注解处理阶段,会调用对应的注解处理器(继承自javax.annotation.processing.AbstractProcessor的子类),在编译时,可以执行注解的一些逻辑,例如生成代码。

在 IDEA 中,如果是 maven 项目,可以通过项目配置指定注解处理器,也可以通过 maven-processor-plugin 实现。

元注解@Target

元注解 @Target 可以有如下8个属性值:

ElementType.ANNOTATION_TYPE

ElementType.CONSTRUCTOR

ElementType.FIELD

ElementType.LOCAL_VARIABLE

ElementType.METHOD

ElementType.PACKAGE

ElementType.PARAMETER

ElementType.TYPE

作用范围看名称基本都能对应上。默认是全部。

开源项目中的使用

Fastjson

Fastjson 作为广泛使用的 Java JSON 解析类库,广泛应用了注解。

字段别名

POJO 中如果使用驼峰命名,但是 API 中需要使用下划线分隔,这样的场景并不少见。

Fastjson 中通过 @JSONField 注解可以实现这一功能。

Fastjson 通过 toJSONString() 方法实现对象转化到 JSON 格式字符串的行为,首先会根据转换对象的类型解析出对象各个字段的信息(参见com.alibaba.fastjson.util.FieldInfo),读取每个字段上的 @JSONField 注解,在转化为字符串过程中,当需要写入键时,如果注解 name 值存在,则写入 name 配置的值。

Spring

AOP

AOP 是常用的编程模式。

在 Spring 中定义一个 Aspect,通过 @Pointcut 注解关联何种对象的何种操作,通过 @Before/@After 等注解指定当前 Aspect 各个阶段可以执行的方法(Advice)。

Spring 框架在扫描各个 bean 时,会根据指定的 Aspect 信息,为各个 bean 的指定方法关联上各个 Advice,在执行时逐个运行。

例如对外提供接口调用时,需要对一些接口提供自定的参数校验等功能,可以考虑通过自定义注解的方式,提供一个 @Around advice,判断参数是否合理即可。

Lombok

Java 开发中对象的 Getter/Setter 方法以及常规的构造方法让代码变得臃肿,Lombok 通过注解的方式,在编译阶段修改 AST,实现生成的 class 文件中带有对应的方法。

以上内容还可以另起篇幅详细说明。

参考

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/129212.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python画图命令

    python画图命令画两张图importmatplotlib.pyplotaspltplt.rcParams[‘font.sans-serif’]=[‘SimHei’]#用来正常显示中文标签plt.rcParams[‘axes.unicode_minus’]=False#用来正常显示负号plt.figure(1)plt.plot(x_data,y_data,color="red",linewidth…

    2022年5月11日
    42
  • Git提交代码步骤

    Git提交代码步骤目录1.Git提交代码步骤1.1第1步:查看当前状态:gitstatus1.2第2步:提交代码到本地git缓存区:gitadd1.3第3步:推送代码到本地git库:gitcommit1.4第4步:合并远程与本地代码:gitpull1.5第5步:提交本地代码到远程仓库:gitpush1.Git提交代码步骤1.1第1步:查看当前状态:gitstatus提交代码第1步:gitstatus查看当前状态当你忘记修改了哪些文件的时候可以使用git..

    2022年6月23日
    44
  • HelixServe搭建局域网流媒体服务器

    HelixServe搭建局域网流媒体服务器查了两天资料,有了些眉目,在成功搭建数次之后把这篇博客补上    但成功搭建并不是一蹴而就的,从开始的一脸懵逼,到中途的困难频繁造访几欲放弃打算转向研究其他实现方式,再到最后的豁然开朗,真应了秀娟说的那句话:    学习的乐趣就在于前期为伊消得人憔悴的酝酿,在于中期一知半解的朦胧,在于后期柳暗花明的顿悟。    不多说了,感谢自己挺过来了,坚持下来,尝到了胜利的喜悦…

    2022年6月6日
    166
  • EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)[通俗易懂]

    EagleEye: Fast Sub-net Evaluation for Efficient Neural Network Pruning(论文阅读)[通俗易懂]目录说明动机贡献方法发现EagleEye剪枝算法实验实验1-相关性的定量分析实验2-基于自适应BN的评估方法的通用性实验3-从修剪候选中选择最佳修剪策略的计算成本实验4-Effectivenessofourproposedmethod总结与讨论说明找出训练好的深度神经网络(DNN)的计算冗余部分是剪枝算法要解决的关键问题。许多算法都试图通过引入各种评估方法来预测修剪后的子网的模型性能。在这个工作中,我们提出了一种称为EagleEye的剪枝方法,其中使用了一个基于自适应批归一化adaptiv

    2022年8月16日
    9
  • echarts中国地图使省份选择性滑动或点击高亮「建议收藏」

    echarts中国地图使省份选择性滑动或点击高亮「建议收藏」本文介绍echarts显示中国省份图,对于需要高亮的省份进行筛选。并且对省份进行选择性交互。首先我们需要一个颜色集合,代表我们要设置多少种颜色。这里用到了dataRange。dataRange:{ show:false, x:’left’, y:’bottom’, splitList:[ …

    2022年10月20日
    4
  • http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html「建议收藏」

    http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html「建议收藏」http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.htmlT

    2022年7月3日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号