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 文件中带有对应的方法。

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

参考

Java通过自定义注解执行方法_Java自定义注解(使用篇)相关推荐

  1. java自定义封装一个方法_Java自定义套件封装教程

    Java自定义套件封装教程 时间:2017-07-28     来源:华清远见JAVA学院 各位亲爱的小伙伴们大家好,近很多伙伴都问我该怎么做Java自定义套件封装,今天华清Java学院小编在这里做了 ...

  2. java哪些类重写equals方法_Java自定义类中重写equals方法

    equals方法的要求: a.自反性:对于任何非空的x,x.equals(x)都应该返回true b.对称性:对于任何引用x和y,当且仅当x.equals(y)返回true时,y.equals(x)也 ...

  3. spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效

    title: "spring同一个类中,一个方法调用另外一个注解(@Transactional)方法时,注解失效" url: "https://wsk1103.githu ...

  4. java注解定义常量_java自定义注解

    1.Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型.该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的c ...

  5. java自定义注解为空值_java自定义注解

    1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.lang.annot ...

  6. java注解获取参数_JAVA 自定义注解及参数获取 | 学步园

    package com.java.annotation; import java.lang.annotation.*; /** * Created by lw on 14-5-30. * 自定义注解 ...

  7. java 注解数组初始化_Java 之 注解的定义

    一.元注解 1.元注解概述 元注解:用于描述注解的注解 2.常用的元注解 (1)@Target:描述注解能够作用的位置 Target 里面是一个 ElementType[] value() 的枚举数组 ...

  8. java中注解的使用_java中注解的使用

    使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节.注解就是用于修饰类.全局变量.方法.参数或局部变量的接口,java中规定,注解的使用 ...

  9. java中容易混淆的方法_java中容易混淆的概念

    java中容易混淆的概念 1. 谈谈 final, finally, finalize 的区别final-修饰符(关键字)如果一个类被声明为 final,意味着它不能再派生出新的子类,不 能作为父类被 ...

最新文章

  1. python会不会出现内存泄露_Python内存泄漏和内存溢出的解决方案
  2. 电脑电视兼容成科技行业新课题
  3. Verilog初级教程(3)Verilog 数据类型
  4. 查找字符位置_查找某个字符最后一次出现的位置
  5. python企业微信回调_python 微信企业号-回调模式接收微信端客户端发送消息并被动返回消息...
  6. php获取python的变量,PHPPython变量交换
  7. 设计模式之_Strategy_01
  8. koa --- restful规范及其栗子
  9. 岛屿类问题的广度优先深度优先双解法(Leetcode题解-Python语言)
  10. XCode10 swift4.2 适配遇到的坑
  11. C++ 基本数据类型 的 字节数
  12. STM32(三)-------流水灯(标准库函数)
  13. 三元运算符(TernaryOperator)
  14. 腾讯通如何修改服务器,rtx如何设置服务器地址
  15. SIFT算法步骤梳理
  16. axure怎么存html文件怎么打开,axure 保存html文件怎么打开
  17. 深度学习中评估指标:准确率Accuracy、召回率Recall、精确率Precision、特异度(真阴性率)和误报率、灵敏度(真阳性率)和漏报率、F1、PR、ROC、AUC、Dice系数、IOU
  18. java设置select选中_按值设置选择选项'selected'
  19. java实现png有损压缩
  20. 证券行业信息化17_我的香港游记3_交易系统技术支持部_会计与结算技术支持部都干些什么?

热门文章

  1. ubuntu 安装、配置FTP
  2. Jquery查找父级添加样式
  3. shell脚本多线程
  4. 【链表】C++链表反转、链表逆序打印
  5. linux怎么修改ftp密码
  6. 网络协议底层原理7——网络安全
  7. 宝塔、云帮手、安全狗、AppNode、WDCP、云锁、悬镜、旗鱼云梯哪个好用?
  8. 60级怀旧服最新服务器人口排名,魔兽世界怀旧服人口普查2019 wow怀旧服人口比例查询最新...
  9. 万能word转换成pdf转换器下载
  10. 倾角传感器如何通过精度和分辨率进行选型