Java 註解原理

下面來看看Java中註解是如何實現的java

建立註解類Inter:函數

Java 註解原理

 

建立測試類Test:測試

Java 註解原理

 

在程序第二句設置斷點,能夠看到:3d

Java 註解原理

 

能夠看到,註解的實例是一個動態代理類的對象.代理

要想查看這個動態代理類,能夠在代碼中加調試

System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

添加系統代理,將其導出爲class文件對象

Java 註解原理

 

能夠看到以下兩個文件:blog

Java 註解原理

 

反編譯$Proxy1.class,以下:繼承

Java 註解原理

 

能夠看到,動態代理類是咱們定義的註解實現類,反編譯Inner.class,以下:索引

Java 註解原理

 

能夠看到,註解接口繼承了java.lang.annotation.Annotation, 經過查看源碼,該類源碼以下:

Java 註解原理

 

能夠看到, 該類下的方法都被$Proxy1動態代理類實現了.

到此處,咱們已經知道Inner註解(接口)是一個繼承了Annotation接口的特殊接口,而咱們經過反射獲取註解時,返回的是Java運行時生成的動態代理對象$Proxy1,該類就是Inner註解(接口)的具體實現類。

那麼, 代理類是如何處理方法的調用的呢?

咱們知道, 動態代理方法的調用最終會傳遞給綁定的InvocationHandler實例的invoke方法處理。咱們能夠看看$Proxy1的源碼

Java 註解原理

 

其中語句調用了父類的成員變量,其父類爲Proxy, 查看該成員變量,以下:

Java 註解原理

 

能夠看到, h對象類型就是InvocationHandler接口的某個實現類

咱們在Proxy類的構造方法處設置斷點:

Java 註解原理

 

經過斷點能夠查看h具體是哪一個對象:

Java 註解原理

 

能夠看到, 該動態代理類爲AnnotationInvocationHandler對象, 查看該類的invoke方法以下:

Java 註解原理

 

其中的memberValues變量是以方法名爲key,以變量爲value的, 以下:

Java 註解原理

 

那麼,這個memberValues變量是從哪來的呢?

Java 註解原理

 

能夠看到,其是在構造函數中進行設置的.

反編譯咱們的Test類,看到:

Java 註解原理

 

因此中間有一個類,負責建立代理對象AnnotationInvocationHandler, 其將變量從常量池中取出並建立map, 進而建立代理對象, 這個類就是 AnnotationParser, 在此不細說了, 感興趣的能夠自行斷點調試查看.


總結

註解本質是一個繼承了Annotation的特殊接口,其具體實現類是Java運行時生成的動態代理類。經過代理對象調用自定義註解(接口)的方法,會最終調用AnnotationInvocationHandler的invoke方法。該方法會從memberValues這個Map中索引出對應的值。而memberValues的來源是Java常量池。

相關文章
相關標籤/搜索