Java注解是嵌入到Java源代码里面的元数据,逻辑上与业务代码耦合,但是结构上与业务代码是分离的。
注解的实现分为三大块:注解的声明,注解注册以及注解的使用。
(1) 注解声明包括两个部分:元注解和声明主体。其中,元注解用来修饰自定义注解本身的,Java提供了4个元注解(Documented, Retention, Inherited和Target)。Documented元注解表示是否将注解添加到Java文档中,Inherited元注解指明子类是否继承该注解, Retention元注解表示该注解的三个生命周期(RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME)。最后,Target元注解表示该注解可以被应用到哪里(ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.ANNOTATION_TYPE, ElementType.PACKAGE)。
声明的主体类似以下格式(只能使用枚举,String和基本数据类型。变量定义使用方法声明的格式, 默认值使用default关键字):
@interface MyAnnotation {
enum ENUM_TYPE {ENUM1, ENUM2} // 枚举类型
ENUM_TYPE myEnum() default ENUM_TYPE.ENUM1; // 枚举类型变量
String myString() default "myString"; // String类型变量
int myInt() default 99; // int类型变量
}
总结一:注解声明的完整格式类似:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
enum ENUM_TYPE {ENUM1, ENUM2} // 枚举类型
ENUM_TYPE myEnum() default ENUM_TYPE.ENUM1; // 枚举类型变量
String myString() default "myString"; // String类型变量
int myInt() default 99; // int类型变量
}
(2) 注解的注册:
注解只能注册在注解声明时指定的Target上,如target定义成Element.METHOD,则注解只能注册在类的方法上。注册形式如下:
@MyAnnotation // 使用默认注解值
public void myMethod() {}
或者,
@MyAnnotation(myEnum=MyAnnotation.ENUM_TYPE.ENUM2) // 指定特定的注解值
public void myMethod() {}
(3) 注解的使用:
使用注解是利用Java的反射机制实现的。如,一个注解注册在RUNTIME的METHOD上,则在运行时,可以通过反射获取类的Method对象,通过Method.getAnnotation()方法可以获取注册在该方法上的注解,进而可以获取该注解的内部状态。
示例代码如下:
MyAnnotation.java:
package com.myAnnotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
enum COLOR {RED, GREEN, BLUE}
COLOR color() default COLOR.GREEN;
String name() default "green";
int size() default 99;
}
AnnotationTest.java:
package com.myAnnotation;
public class AnnotationTest {
public AnnotationTest() {}
@MyAnnotation(color=MyAnnotation.COLOR.RED)
public void dump() {
System.out.println("" + this.getClass() + ".dump()");
}
}
Test.java:
package com.myAnnotation;
import java.lang.reflect.Method;
import java.lang.annotation.*;
public class Test {
public static void main(String[] args) {
AnnotationTest annInstance = new AnnotationTest();
annInstance.dump();
for (Method method: annInstance.getClass().getMethods()) {
System.out.println(method.getName());
MyAnnotation myAnnotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
if (myAnnotation != null) {
System.out.println("Annotation.color:" + myAnnotation.color());
System.out.println("Annotation.name:" + myAnnotation.name());
System.out.println("Annotation.size:" + myAnnotation.size());
}
}
}
}