Java的注解是什么原理?
首先,從一個簡單的注解開始,@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
String value() default "";
}
使用javap -verbose命令查看這個注解的class文件,發現這個注解被編譯成了接口,并且繼承了java.lang.annotation.Annotation接口,接口是不能直接實例化使用的,當在代碼中使用這個注解,并使用getAnnotation方法獲取注解信息時,JVM通過動態代理的方式生成一個實現了Test接口的代理對象實例,然后對該實例的屬性賦值,value值就存在這個代理對象實例中。
如果順著getAnnotation方法繼續跟蹤源代碼,會發現創建代理對象是在AnnotationParser.java中實現的,這個類中有一個annotationForMap方法。在annotationForMap方法內部使用Proxy.newProxyInstance方法在運行時動態創建代理,AnnotationInvocationHandler實現了InvocationHandler接口,當調用代理對象的value()方法獲取注解的value值,就會進入AnnotationInvocationHandler類中的invoke方法,深入invoke方法會發現,獲取value值最終是從AnnotationInvocationHandler類的memberValues屬性中獲取的,memberValues是一個Map類型,key是注解的屬性名,這里就是“value”,value是使用注解時設置的值。
因為回答中不能插入源碼做講解輔助,更多詳細內容可以關注『Java實戰技術』主頁的原創文章《Java注解是如何玩轉的,面試官和我聊了半個小時》。