Introduction
Java 注解(Annotation)是 Java 从 JDK 5 开始引入的一种语法结构,用来为代码添加元数据。比如:
1 2 3 4
| @Override public String toString() { return "Hello"; }
|
在编译过程中,注释会被忽略,但是注解会被编译器打包进.class文件。
自定义注解
Java中,使用 @interface 来定义注解。比如:
1 2 3
| public @interface MyLog { String value() default "default log"; }
|
元注解
元注解是可以修饰其他注解的注解。
@Taregt 可以定义注解能够被应用于源码的哪些位置。
- ElementType.TYPE:类或接口
- ElementType.FIELD:字段
- ElementType.METHOD:方法
- ElementType.CONSTRUCTOR:构造方法
- ElementType.PARAMETER:方法参数
@Retention定义了注解要在 Java 编译流程的哪个阶段保留。
- SOURCE:只保留在源码中,编译时就扔掉。
- CLASS:保留在 .class 文件中,但 JVM 运行时无法读取。比如用于指导编译器如何生成字节码。
- RUNTIME:保留到运行时,可以用反射获取。Spring的注解都属于RUNTIME。
语法
比如我想定义一个 @Check 注解,标记在方法上,然后在程序运行的时候,自动检查这个注解是否存在,并打印 value 的内容。
1 2 3 4 5 6 7 8 9 10 11 12
| public class MyService { @Check("正在检查这个方法") public void doSomething() { System.out.println("Do Something..."); } }
|
定义注解:
1 2 3 4 5 6 7 8 9 10 11
| import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check { String value(); }
|
使用注解的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class MyService {
@Check("正在检查这个方法") public void doSomething() { System.out.println("Do Something..."); }
@Check("另一个需要检查的方法") public void anotherThing() { System.out.println("Do Another Thing..."); }
public void noCheck() { System.out.println("这个方法没有注解,不用检查"); } }
|
写一个注解处理器,用反射来读取注解信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import java.lang.reflect.Method;
public class CheckProcessor { public static void main(String[] args) throws Exception { MyService service = new MyService();
Class<?> clazz = service.getClass();
for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(Check.class)) { Check checkAnnotation = method.getAnnotation(Check.class); System.out.println("检查到方法: " + method.getName()); System.out.println("注解的值是: " + checkAnnotation.value());
method.invoke(service); System.out.println("-----------------------------"); } } } }
|