@Override,@Deprecated,@SuppressWarnings为常见的3个注解。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface NativeQuery { String value() default ""; boolean pagable() default false; boolean withGroupby() default false; Class<?> model() default DEFAULT.class; Class<? extends ColumnTranslator> translator() default DummyColumnTranslator.class; String[] alias() default {}; Class<?>[] clazzes() default {}; public static final class DEFAULT {} }
注解@Retention 可以用来修饰注解,是注解的注解,称为元注解。
Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型,
这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 RententionPolicy使用。RetentionPolicy有3个值:CLASS RUNTIME SOURCE
用@Retention(RetentionPolicy.CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候;
用@Retention(RetentionPolicy.SOURCE )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中;
用@Retention(RetentionPolicy.RUNTIME )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时,
所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 可以让你从JVM中读取注解N注解的信息,以便在分析程序的时候使用.
注解@Target 也是用来修饰注解的元注解,它有一个属性ElementType也是枚举类型,
值为:ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE
如@Target(ElementType.METHOD) 修饰的注解表示该注解只能用来修饰在方法上。
@Target:指定程序元定义的注释所使用的地方,它使用了另一个类:ElementType,是一个枚举类定义了注释类型可以应用到不同的程序元素以免使用者误用。看看java.lang.annotation
ElementType是一个枚举类型,指明注释可以使用的地方,看看ElementType类:
public enum ElementType {
TYPE, // 指定适用点为 class, interface, enum
FIELD, // 指定适用点为 field
METHOD, // 指定适用点为 method
PARAMETER, // 指定适用点为 method 的 parameter
CONSTRUCTOR, // 指定适用点为 constructor
LOCAL_VARIABLE, // 指定使用点为 局部变量
ANNOTATION_TYPE, //指定适用点为 annotation 类型
PACKAGE // 指定适用点为 package
}
/** * Created by hailong on 2016/11/21. */ @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String hello() default "gege"; String world(); int[] array() default { 2, 4, 5, 6 }; Class style() default String.class; }
@MyAnnotation(hello = "beijing", world="shanghai",array={},style=int.class) public class MyTest { @MyAnnotation(world = "shanghai",array={1,2,3}) @Deprecated @SuppressWarnings("") public void output() { System.out.println("output something!"); } }
public class MyReflection { public static void main(String[] args) throws Exception { MyTest myTest = new MyTest(); Class<MyTest> myTestClass = MyTest.class; // 方法 Method method = myTestClass.getMethod("output", new Class[] {}); // 如果MyTest类名上有注解@MyAnnotation修饰,则为true // 类 if(MyTest.class.isAnnotationPresent(MyAnnotation.class)) { System.out.println("have annotation"); } if (!method.isAnnotationPresent(MyAnnotation.class)) { } else { method.invoke(myTest, null); //调用output方法 //获取方法上注解@MyAnnotation的信息 MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); String hello = myAnnotation.hello(); String world = myAnnotation.world(); System.out.println(hello + ", " + world);//打印属性hello和world的值 System.out.println(myAnnotation.array().length);//打印属性array数组的长度 System.out.println(myAnnotation.style()); } //得到output方法上的所有注解,当然是被RetentionPolicy.RUNTIME修饰的 Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); } } }
设定类属性值后,在框架里会有class用反射机制设定具体方法实现方式。