アノテーションのインスタンスはDynamic Proxyです。
確認してみる
こんな感じのアノテーションを定義して、
package com.example;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface FooBar {
}
こんな感じでアノテーションのインスタンスからClass
を書き出すコードを書いて、
package com.example;
@FooBar
public class Main {
public static void main(final String[] args) {
final FooBar a = Main.class.getAnnotation(FooBar.class);
System.out.println(a.getClass());
}
}
実行すると次の出力を得られました。
出力
class com.sun.proxy.$Proxy1
ご覧の通り(?)Dynamic Proxyですね。
Dynamic Proxyはどこで作られているのか
Class.getAnnotation
を辿るとAnnotationParser.annotationForMap
へ行き着きます。
コードを見るとアノテーションのClass
を使ってDynamic Proxyが作られていることが分かります。
/**
* Returns an annotation of the given type backed by the given
* member {@literal ->} value map.
*/
public static Annotation annotationForMap(final Class<? extends Annotation> type,
final Map<String, Object> memberValues)
{
return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
public Annotation run() {
return (Annotation) Proxy.newProxyInstance(
type.getClassLoader(), new Class<?>[] { type },
new AnnotationInvocationHandler(type, memberValues));
}});
}
Dynamic Proxyを作るときに渡されるInvocationHandler
実装はAnnotationInvocationHandler
です。
アノテーションに対するメソッド呼び出しは全てAnnotationInvocationHandler
によって処理されます。
アノテーションのインスタンスからAnnotationInvocationHandler
を取得したくなったらProxy.getInvocationHandler
を使います。
final FooBar a = ...
final InvocationHandler h = Proxy.getInvocationHandler(a);
System.out.println(h.getClass());
出力
class sun.reflect.annotation.AnnotationInvocationHandler
補足情報
そもそもDynamic Proxyってなんや?という方はProxy
とInvocationHandler
のJavadocをご参照ください。