注解的作用: 1.生成文档 这是最常见的,也是java 最早提供的注解。常用的有 @see @param @return 等 2.跟踪代码依赖性,实现替代配置文件功能 Spring中大量运用注解来简化配置文件 3.在编译时进行格式检查 如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出 实现一个简单的注解:
@Retention(RetentionPolicy.RUNTIME) public @interface MyTarget { }
上面是一个最简单的注解实现,没有定义任何的属性 需要注意的是@Retention(RetentionPolicy.RUNTIME)是定义注解所必须的。 @Retention是注解的注解,称为注解的元注解。 括号里有一个枚举类型的值,即为注解内部定义的值。打开Retention的实现:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { RetentionPolicy value(); }
可以看到这里定义了一个变量value并且没有缺省值,所以不写这个value就会报错。 继续打开RetentionPolicy:
public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }
可以发现这个枚举类定义了三个值,这三个值分别代表的是我们定义的MyTarget如何保持。 @Retention(RetentionPolicy.CLASS) 注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候 @Retention(RetentionPolicy.SOURCE) 注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中 @Retention(RetentionPolicy.RUNTIME) 注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时 还需要注意的是java的元注解一共有四个: @Document @Target @Retention @Inherited 各个的作用,读者自己查一下吧。 注解处理的一个基础:T getAnnotation(Class annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。 Annotation[] getAnnotations(): 返回该程序元素上存在的所有注解。 boolean is AnnotationPresent(Class annotationClass): 判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false. Annotation[] getDeclaredAnnotations(): 返回直接存在于此元素上的所有注释。 与此接口中的其他方法不同,该方法将忽略继承的注释。 (如果没有注释直接存在于此元素上,则返回长度为零的一个数组。) 该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。 实现为属性赋值的注解:
package com.justin.test.util; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface CarNameTarget { String name() default ""; }
package com.justin.test.util; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface CarSalerTarget { String salerName(); int age() default 1; }
package com.justin.test.entity; import com.justin.test.util.CarNameTarget; import com.justin.test.util.CarSalerTarget; /** * 描述: * 汽车实体类 * * @author 孫兵 * @create 2018-05-15 10:16 */ public class BnechCar { @CarNameTarget(name = "奔驰") private String name; @CarSalerTarget(salerName = "justin", age = 22) private String salerInfo; }
package com.justin.test.util; import java.lang.reflect.Field; /** * 描述: * 汽车信息工具类 * * @author 孫兵 * @create 2018-05-15 10:19 */ public class CarInfoUtil { public static void getFruitInfo(Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(CarNameTarget.class)) { CarNameTarget carNameTarget = field.getAnnotation(CarNameTarget.class); String carColour = "汽车的中文名:" + carNameTarget.name(); System.out.println(carColour); } else if (field.isAnnotationPresent(CarSalerTarget.class)) { CarSalerTarget carSalerTarget = field.getAnnotation(CarSalerTarget.class); String salerInfo = "销售员姓名:" + carSalerTarget.salerName() + ",年龄:" + carSalerTarget.age(); System.out.println(salerInfo); } } } }
/** * 自定义注解测试 */ private void targetTest() { CarInfoUtil.getFruitInfo(BnechCar.class); }
打印信息:
汽车的中文名:奔驰 销售员姓名:justin,年龄:22