Java注解实际上就是一个继承自java.lang.annotatAnnotation的接口。而其具体的实现就是一个通过JDK代理实现的动态代理类。
如何去验证这一点呢?
1. 编写一个简单注解
java
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
String value();
}
再通过cmd进入到该文件所在路径,进行编译与发编译。
2. 编译后用 javap
反编译
bash
javac AnnotationTest.java
javap -p AnnotationTest
得到如下结果:

这就说明,注解的实现本质上还是一个接口,继承自java.lang.annotatAnnotation,我们在注解中定义的所谓的'参数'------value,实际上还是接口中的抽象方法。
那么这个怎么去验证注解的具体实现本质上是通过JDK动态代理实现的呢?
我们可以通过运行以下代码:
java
package com.company.annotation;
import java.lang.reflect.Proxy;
@AnnotationTest("hash-yang")
class Demo{
}
public class AnnotationDemo {
public static void main(String[] args) {
//设置 JDK 会把所有动态生成的代理类字节码保存到当前目录(根目录)
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
AnnotationTest annotation = Demo.class.getAnnotation(AnnotationTest.class);
System.out.println(annotation.getClass());
System.out.println(Proxy.isProxyClass(annotation.getClass()));
}
}
运行产生以下的目录以及文件:

在其中就是我们这段代码运行时,所有JDK动态代理生成的代理类
proxy0是我们元控制注解的保留策略的注解@Retention的代理类

而$proxy2就是我们的AnnotationTest自定义注解的动态代理类:
java
public final class $Proxy1 extends Proxy implements AnnotationTest {
//其中方法0123都是来自Annotation接口的父类Object的方法,由代理类进行了相应的重写,
//其中方法3就是实现的返回我们定义的参数值------value的一个函数
//而方法5就是在Annotation接口中的annotationType,用于返回当前注解的类型(interface com.company.annotation.AnnotationTest)
private static final Method m0;
private static final Method m1;
private static final Method m2;
private static final Method m3;
private static final Method m4;
public $Proxy1(InvocationHandler var1) {
super(var1);
}
public final int hashCode() {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final boolean equals(Object var1) {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String value() {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Class annotationType() {
try {
return (Class)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.company.annotation.AnnotationTest").getMethod("value");
m4 = Class.forName("com.company.annotation.AnnotationTest").getMethod("annotationType");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(((Throwable)var2).getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(((Throwable)var3).getMessage());
}
}
private static MethodHandles.Lookup proxyClassLookup(MethodHandles.Lookup var0) throws IllegalAccessException {
if (var0.lookupClass() == Proxy.class && var0.hasFullPrivilegeAccess()) {
return MethodHandles.lookup();
} else {
throw new IllegalAccessException(var0.toString());
}
}
}
最终注解中的方法的调用都会走到AnnotationInvocationHandler的invoke方法。