Java Annotations: Explored Explained--转载
原文地址:http://www.javacodegeeks.com/2012/08/java-annotations-explored-explained.html
One of the many wonderful features of Java 5 SE is the introduction of the Annotations construct.
Annotations are tags that we can insert into our program source code for some tool to process it and make sense out of it. Annotations processing tools generally use Reflection API (of Java 5 SE) to process the code at source level on Java code or bytecode level to process the class files into which the compiler has placed the annotations. Java Annotations are wonderfully explained in many places around the web, but the only place where I could find a sensible and complete example was a hard bound book by Prentice Hall Publications named Core Java : Volume II – Advanced Features, authored by Cay S. Horstmann and Gary Cornell.
Almost all the places on web that try to explain Annotations miss the most crucial part of showing us an Annotation Processing Tool (APT) for our custom written annotations and the way to use it from our code. I have used the information from the book to build some Annotations for validating variables and initializing values in them from property files for my project. My observation of the lack of examples over the www for writing custom Java Annotations has motivated me to write this article. So, presenting to you a sample custom Java Annotation to help you write your own Annotations for whatever it is you may be doing.
I will take you through the NullValueValidate
annotation whose purpose as its name suggests is to validate the variable it annotates to be containing a non null value. If it finds a null value while processing then it will throw aNullPointerException
.
Declaring an Annotation
Lets begin by declaring our annotation. This declaration will be used by the code that intends to use the annotation to annotate the variables in its object.
01
|
package annotation.declaration;
|
02
|
import java.lang.annotation.Documented;
|
03
|
import java.lang.annotation.ElementType;
|
04
|
import java.lang.annotation.Retention;
|
05
|
import java.lang.annotation.RetentionPolicy;
|
06
|
import java.lang.annotation.Target;
|
07
|
08
|
/**
|
09
|
* Null Value Validate is, as the name suggests an annotation to
|
10
|
* validate whether the parameter is null or not
|
11
|
* @author Y.Kamesh Rao
|
12
|
*
|
13
|
*/
|
14
|
@Documented
|
15
|
@Target (ElementType.FIELD)
|
16
|
@Retention (RetentionPolicy.RUNTIME)
|
17
|
18
|
public @interface NullValueValidate {
|
19
|
String paramName();
|
20
|
}
|
Note the ‘@’(AT) symbol in front of the ‘interface’ keyword. This is the syntax used to declare an annotation. This is called an annotation interface. The methods of the interface correspond to the elements of the annotation. paramName()
– This is the only element our annotation declaration consists of. It stores the name of the annotated field to display it in a message while processing. Note that the declaration looks like a function declaration. Actually, that is what it is. @interface
actually declares a Java interface whose implementation is provided by the objects that use the annotation. Annotation processors receive the objects that use/implement the annotation and they call annotation interface methods to retrieve the annotation elements. In our case, the NullValueValidateAnnotationProcessor
would receive the object of the class that has some fields annotated using the NullValueValidate
annotation. This processor would then call the paramName()
method to retrieve the value of this annotation element.
We use 3 of the Java provided Annotations to annotate the properties of our declaration. These are alternatively referred to as the Built-In Annotations and are used for ‘Annotating an Annotation’. (Well, there are much tougher tongue twisters than this). @Documented
– Indicates that the annotation declaration has to be included while creating the docs for this project using JavaDocs. By default, Annotations are excluded from the documentation generated using the javadocs
command. @Target
– Indicates the target elements in your java program to which the annotation shall be applied. It can either the Field, Method, Class or the whole Package itself. Our NullValueValidate
annotation shall be applicable to only class fields. Here are the possible values taken by this Enum –
- TYPE – Applied only to Type. A Type can be a Java class or interface or an Enum or even an Annotation.
- FIELD – Applied only to Java Fields (Objects, Instance or Static, declared at class level).
- METHOD – Applied only to methods.
- PARAMETER – Applied only to method parameters in a method definition.
- CONSTRUCTOR – Can be applicable only to a constructor of a class.
- LOCAL_VARIABLE – Can be applicable only to Local variables. (Variables that are declared within a method or a block of code).
- ANNOTATION_TYPE – Applied only to Annotation Types.
- PACKAGE – Applicable only to a Package.
@Retention
- Indicates the retention policy to be used for the annotation. In simple words, for long would we retain the annotation. There are three possible values –
- SOURCE – Annotations are to be discarded by the compiler.
- CLASS – Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. This is the default behavior.
- RUNTIME – Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
We have set the RetentionPolicy
to be RUNTIME
since we plan to process the annotations at runtime of the program.@Target
and @Retention
are also called Meta-Annotations.
Annotation Processing Tool
An annotation processor tool, parses the object it receives and takes programmed actions on finding the annotations it is processing in the object under scrutiny. Here is the annotation processor for our previously declared annotation –NullValueValidate
.
01
|
package annotation.processor;
|
02
|
03
|
import java.lang.annotation.Annotation;
|
04
|
import java.lang.reflect.Field;
|
05
|
import annotation.declaration.NullValueValidate;
|
06
|
07
|
/**
|
08
|
* The class file to actually carry out the validations
|
09
|
* for the various validate annotations we have declared
|
10
|
* @author Y.Kamesh Rao
|
11
|
*/
|
12
|
public class NullValueValidateAnnotationProcessor {
|
13
|
/**
|
14
|
* Method to process all the annotations
|
15
|
* @param obj The name of the object where
|
16
|
* annotations are to be identified and
|
17
|
* processed
|
18
|
*/
|
19
|
public static void processAnnotations(Object obj) {
|
20
|
try {
|
21
|
Class cl = obj.getClass();
|
22
|
23
|
// Checking all the fields for annotations
|
24
|
for (Field f : cl.getDeclaredFields()) {
|
25
|
// Since we are Validating fields, there may be many
|
26
|
// NullPointer and similar exceptions thrown,
|
27
|
// so we need to catch them
|
28
|
try {
|
29
|
// Processing all the annotations on a single field
|
30
|
for (Annotation a : f.getAnnotations()) {
|
31
|
// Checking for a NullValueValidate annotation
|
32
|
if (a.annotationType() == NullValueValidate. class ) {
|
33
|
NullValueValidate nullVal = (NullValueValidate) a;
|
34
|
System.out.println( 'Processing the field : ' + nullVal.paramName());
|
35
|
36
|
// Setting the field to be accessible from our class
|
37
|
// is it is a private member of the class under processing
|
38
|
// (which its most likely going to be)
|
39
|
// The setAccessible method will not work if you have
|
40
|
// Java SecurityManager configured and active.
|
41
|
f.setAccessible( true );
|
42
|
43
|
// Checking the field for a null value and
|
44
|
// throwing an exception is a null value encountered.
|
45
|
// The get(Object obj) method on Field class returns the
|
46
|
// value of the Field for the Object which is under test right now.
|
47
|
// In other words, we need to send 'obj' as the object
|
48
|
// to this method since we are currently processing the
|
49
|
// annotations present on the 'obj' Object.
|
50
|
if (f.get(obj) == null ) {
|
51
|
throw new NullPointerException( 'The value of the field ' +f.toString()+ ' can' t be NULL.');
|
52
|
} else
|
53
|
System.out.println( 'Value of the Object : ' +f.get(obj));
|
54
|
}
|
55
|
}
|
56
|
} catch (Exception e) {
|
57
|
System.out.println(e.getMessage());
|
58
|
e.printStackTrace();
|
59
|
}
|
60
|
}
|
61
|
} catch (Exception e) {
|
62
|
System.out.println(e.getMessage());
|
63
|
e.printStackTrace();
|
64
|
}
|
65
|
}
|
66
|
}
|
Most of the code is self explanatory with comments that it has. Please refer the code for detailed understanding of the same. Basically, it has a static method called processAnnotations
that takes the object of the class which contains annotations that need to be processed. We then use Java Reflection API to process each of the Field in this received object parameter and take necessary actions of null value validation whenever we find a NullValueValidate
Annotation on the field. If a null value is found, we throw the NullPointerException
or we print the value on the console.
Annotation UsagePlease refer the following code that uses the NullValueValidate
annotation that we just implemented. It also uses the NullValueValidateAnnotationProcessor
to process the declared annotations on its field at runtime by calling it from its constructor. Also do note that the annotations are used in a similar fashion as access modifiers like private or public with the variable/field declarations. Usually a newline is entered for better readability of the code. Else, the annotation can very well exist in the same line as the variable/field declaration. The name of the annotation is preceded by an ‘@’(AT) symbol.
01
|
package annotation;
|
02
|
03
|
import annotation.declaration.NullValueValidate;
|
04
|
import annotation.processor.NullValueValidateAnnotationProcessor;
|
05
|
06
|
/** Main class to test the Annotations
|
07
|
* @author Y.Kamesh Rao
|
08
|
*/
|
09
|
public class AnnotationExample {
|
10
|
@NullValueValidate (paramName = 'testVar1' ) private String testVar1;
|
11
|
@NullValueValidate (paramName = 'testVar2' ) private String testVar2;
|
12
|
13
|
14
|
public AnnotationExample() {
|
15
|
testVar2 = 'Testing the Null Value Validation...It Works...!' ;
|
16
|
|
17
|
// Calling the processor to process the annotations applied
|
18
|
// on this class object.
|
19
|
NullValueValidateAnnotationProcessor.processAnnotations( this );
|
20
|
}
|
21
|
|
22
|
public static void main(String args[]) {
|
23
|
AnnotationExample ae = new AnnotationExample();
|
24
|
}
|
25
|
}
|
Output
1
|
Processing the field:testVar1
|
2
|
Value of the Object:Testing the Null Value Validation...It Works...!
|
3
|
Processing the field:testVar2
|
4
|
The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.
|
5
|
java.lang.NullPointerException:The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.
|
6
|
at annotation.processor.NullValueValidateAnnotationProcessor.processAnnotation
|
7
|
(NullValueValidateAnnotationProcessor.java: 66 )
|
8
|
at annotation.AnnotationExample.(AnnotationExample.java: 28 )
|
9
|
at annotation.AnnotationExample.main(AnnotationExample.java: 33 )
|
Conclusion
I had a lot of fun doing this sample annotation program and now I have implemented many custom made Annotations to load properties from property files, validations of database field lengths, etc. Annotations greatly reduces the verbosity of the code thus making it much simpler and readable. Annotations can be used for logging, generating code dependent deployment descriptors and other mechanical and repetitive jobs. I had a lot of fun compiling this article for you guys. I hope you benefit from it.
转载于:https://www.cnblogs.com/davidwang456/p/4415146.html
Java Annotations: Explored Explained--转载相关推荐
- Processing Java Annotations Using Reflection
(转载)https://keyholesoftware.com/2014/09/15/java-annotations-using-reflection/ In my previous article ...
- java 包含汉字,【转载】Java判断字符串中是不是包含汉字
[转载]Java判断字符串中是否包含汉字 import java.util.regex.Matcher; import java.util.regex.Pattern; public class If ...
- 8张图带你理解Java整个只是网络(转载)
8张图带你理解Java整个只是网络 一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选.如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟. 1.字符 ...
- 深入理解 Java 内存模型(转载)
摘要: 原创出处 http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 「zhisheng」欢迎转载,保留摘要,谢谢! 0. 前提 &l ...
- JAVA socket编程实例 转载
事实上网络编程简单的理解就是两台计算机相互通讯数据而已.对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了.Java SDK提供一些相对简单的Api来完成这些工作.Socket ...
- Coroutine in Java - Quasar Fiber实现--转载
转自 https://segmentfault.com/a/1190000006079389?from=groupmessage&isappinstalled=0 简介 说到协程(Corout ...
- 25个Java机器学习工具库--转载
本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...
- Active Object 并发模式在 Java 中的应用--转载
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-activeobject/ 本文主要从以下两个方面进行阐述: 使用 C++ 语言,来描述 Act ...
- java 开源缓存框架--转载
原文地址:http://www.open-open.com/13.htm JBossCache/TreeCache JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改 ...
最新文章
- 【转】《iOS7 by Tutorials》系列:iOS7的设计精髓(上)
- postman 以全局变量活用 Token
- CSS层叠样式表进阶
- TCP 三次握手 和 四次挥手
- PyCharm光标变粗的解决办法
- (23)System Verilog设计二分频电路
- Linux中Redis的安装
- win10怎么设置默认浏览器_如何将浏览器设置为默认浏览器?最简单的方法
- chrome浏览器不展示地址栏的完整路径解决
- 关于微信小程序的视频的坑
- 蓝桥杯备战(一)3n+1问题
- 优先部署EDI系统把握信息传输的主动权
- 电脑连接安卓手机摄像头的方法(含DroidCam安装包及简明使用教程)
- vue axios封装及使用
- 想成为华为hcie网络工程师一定鸦知道的MSDP 基本介绍
- 广告中的CPM、CPC、CPA解释
- 什么是运算计算机科学的基础概念,【软件设计师】笔记一:计算机科学基础知识...
- 数控机床需要c语言程序吗,数控机床的编程有几种方法?
- IT 行业中Dev、RD、CPO、TeamLeader、QA、PM、PO ,HC,TL 分别是什么的简称,他们分别对应的职责是什么?
- GPU图形图像渲染原理
热门文章
- xampp php源码的路径,php – XAMPP中的根路径
- pandas 判断数据表中的缺失值
- 计算机未来的储存装置,图说计算机存储设备
- php mysql update 返回_php mysql_query增删改查(update delete insert)返回值类型
- php记录网站访问,PHP简单实现记录网站访问量的功能
- java 文件路径表达式_Java基础(二十二) Lambda表达式和File类
- sklearn支持gpu_Keras Sklearn随机搜索GPU OOM
- dl 系列服务器,DL系列服务器内存总结..doc
- 采用 opencv surf 算子进行特征匹配
- sql array 数组基本用法(二)