Java魔法堂:自定义和解析注解
一、前言
注解(Annotation)作为元数据的载体,为程序代码本身提供额外的信息,使用过MyBatis等ORM框架的朋友对 @Insert 的注解应该不陌生了,这是MyBatis自定义的注解,显然我们也可以按需求自定义一些注解,然后对其进行解析获取元数据,进而实现通过代码生成代码的操作。
二、自定义注解
只需通过 关键字@interface 即可自定义注解
// 标识注解(就是无属性的注解)
public @interface AnnotationWithoutProperty{
}
// 带value属性的注解
public @interface AnnotationWithVal{
String value();
}
// 带myVal属性的注解
public @interface AnnotationWithMyVal{
String[] myValue();
}
// 带value和myVal属性的注解
public @interface AnnotationWith2Val{
String value();
String[] myValue();
}
// 带缺省值的myVal属性的注解
public @interface AnnotationWithDefaultVal{
String myVal() default "hello world!";
}
使用方式如下:
@AnnotationWithoutProperty
@AnnotationWithVal("hello world") // value属性赋值时,不用显式写出属性名
@AnnotationWithMyVal(myValue={"hello", "world"}) // 其他属性赋值时,必须显示写出属性名
@AnnotationWith2Val(value="hello world", myVal={"hello", "world"})
@AnnotationWithDefaultVal // 属性拥有缺省值时,不必显示设置属性值
@AnnotationWithDefaultVal("new value")
public void test(){}
三、注解的注解
注解的注解就是为注解本身提供额外的信息,从而约束或增强注解的能力。其中包含有 @Documented
、 @Inherited
、 @Target
、 Retention
4种注解。
@Target注解 :用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败。
// 约束@MyAnnotation的作用范围是函数和构造函数
@Target(ElementType.METHOD, ElementType.CONSTRUCTOR)
public @interface MyAnnotation{}
@Retention注解 :用于约束被描述的注解的作用范围,注解的作用范围有三个,分别为
1. RetentionPolicy.SOURCE ,作用范围为源码,就是仅存在于java文件中,当执行 javac 命令时将会去除该注解。
2. RetentionPolicy.CLASS ,作用范围为二进制码,就是存在于class文件中,当执行 java 命令时会去除该注解。
3. RetentionPolicy.RUNTIME ,作用范围为运行时,就是我们可以通过反射动态获取该注解。
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{}
@Documented注解 :用于指定javadoc生成API文档时显示该注解信息
@Inherited注解 :用于指定被描述的注解可以被其所描述的类的子类继承。默认情况
// 默认注解不会被子类继承
@MyAnnotation
public class Parent{}
// Son并没有继承注解MyAnnotation
public class Son extends Parent{}
通过 @Inherited 子类将会继承父类的 @MyAnnoation注解 。
四、读取注解
通过反射我们可以获取类、函数等上的注解信息。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CLASS)
@Documented
public @interface MyAnnotaion{
String value() default "hello world";
}
@MyAnnotation
public class Test{
public static void main(String[] args){
MyAnnotation ma = Test.class.getAnnotation(MyAnnotation.class);
System.out.println(ma.value());
// 获取自身和从父类继承的注解
Annotation[] annotations = Test.class.getAnnotations();
// 仅获取自身的注解
Annotation[] annotations = Test.class.getDeclaredAnnotations();
}
}
五、参考
http://www.cnblogs.com/liubiqu/archive/2008/06/01/1211503.html
- 【译】使用Apache的mod重写来保护你的C2 Empire
- 大白话,设计一个购物车对象
- 【译】Cromos – 下载并注入代码到谷歌 Chrome 浏览器扩展中
- X-NUCA 2017第三期 WriteUp
- 学习分享 | Flipped Ciphertext Bits
- 聊一下JavaScript定时器
- java redis 通用组建
- 学习分享 | Padding Oracle
- FastJson 反序列化注意事项
- Python编写渗透工具学习笔记二 | 0x05编写脚本劫持tcp会话
- linux下socket编程
- java与openssl的rsa算法互
- Python编写渗透工具学习笔记二 | 0x04编写程序分析流量检测ddos攻击
- Python编写渗透工具学习笔记二 | 0x03用python构建ssh僵尸网络
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- C语言CGI编程入门(一)
- android RecycleView实现下拉刷新和上拉加载
- 解析Android 8.1平台SystemUI 导航栏加载流程
- Mysql系列第二十二讲 mysql索引管理详解
- Android自定义View实现五子棋小游戏
- 通过.htaccess防盗链
- Android实现聊天记录上传本地服务器(即时通讯)
- Android10.0实现本地音乐播放(附源码下载)
- python - 获取网站PR及百度权重
- 详解Android Studio3.5及使用AndroidX的一些坑
- AndroidQ分区存储权限变更及适配的实现
- Gradle的缓存路径修改的四种方法(小结)
- 适配AndroidQ拍照和读取相册图片的实现方法
- 这是我的第一篇文章
- Android自定义View实现五子棋游戏