一文读懂注解的底层原理
点击上方老周聊架构关注我
一、前言
注解类型声明中的标识符指定了注解类型的名称。
如果注解类型与它的任何封闭类或接口具有相同的简单名称,则编译时会出现错误。
每个注解类型的直接父接口都是 java.lang.annotation.Annotation。
二、注解的底层实现
(RetentionPolicy.RUNTIME)
(ElementType.TYPE)
public RateLimit {
int value() default 0;
}
@RateLimit(value = 666)
public class RateLimitMain {
public static void main(String[] args) {
RateLimit rateLimit = RateLimitMain.class.getAnnotation(RateLimit.class);
System.out.println(rateLimit.value());
}
}
javap -c -v RateLimit.class
Classfile /Users/Riemann/Code/spring-boot-demo/target/classes/com/riemann/springbootdemo/annotation/RateLimit.class
Last modified 2021-3-23; size 495 bytes
MD5 checksum 1ce59bd6cc4c7297e8d3f032320b04d3
Compiled from "RateLimit.java"
public interface com.riemann.springbootdemo.annotation.RateLimit extends java.lang.annotation.Annotation
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
Constant pool:
#1 = Class #18 // com/riemann/springbootdemo/annotation/RateLimit
#2 = Class #19 // java/lang/Object
#3 = Class #20 // java/lang/annotation/Annotation
#4 = Utf8 value
#5 = Utf8 ()I
#6 = Utf8 AnnotationDefault
#7 = Integer 0
#8 = Utf8 SourceFile
#9 = Utf8 RateLimit.java
#10 = Utf8 RuntimeVisibleAnnotations
#11 = Utf8 Ljava/lang/annotation/Retention;
#12 = Utf8 Ljava/lang/annotation/RetentionPolicy;
#13 = Utf8 RUNTIME
#14 = Utf8 Ljava/lang/annotation/Documented;
#15 = Utf8 Ljava/lang/annotation/Target;
#16 = Utf8 Ljava/lang/annotation/ElementType;
#17 = Utf8 TYPE
#18 = Utf8 com/riemann/springbootdemo/annotation/RateLimit
#19 = Utf8 java/lang/Object
#20 = Utf8 java/lang/annotation/Annotation
{
public abstract int value();
descriptor: ()I
flags: ACC_PUBLIC, ACC_ABSTRACT
AnnotationDefault:
default_value: I#7}
SourceFile: "RateLimit.java"
RuntimeVisibleAnnotations:
0: #11(#4=e#12.#13)
1: #14()
2: #15(#4=[e#16.#17])
注解是一个接口,它继承自 java.lang.annotation.Annotation 父接口。
@RateLimit 自身定义了一个抽象方法 public abstract int value(); 。
三、揭秘注解背后的代理类
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
...
}
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
// annotation data that might get invalidated when JVM TI RedefineClasses() is called
private static class AnnotationData {
final Map<Class<? extends Annotation>, Annotation> annotations;
final Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
// Value of classRedefinedCount when we created this AnnotationData instance
final int redefinedCount;
AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations,
Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
int redefinedCount) {
this.annotations = annotations;
this.declaredAnnotations = declaredAnnotations;
this.redefinedCount = redefinedCount;
}
}
private AnnotationData annotationData() {
while (true) { // retry loop
AnnotationData annotationData = this.annotationData;
int classRedefinedCount = this.classRedefinedCount;
if (annotationData != null &&
annotationData.redefinedCount == classRedefinedCount) {
return annotationData;
}
// null or stale annotationData -> optimistically create new instance
AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);
// try to install it
if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {
// successfully installed new AnnotationData
return newAnnotationData;
}
}
}
static <T> boolean casAnnotationData(Class<?> clazz,
AnnotationData oldData,
AnnotationData newData) {
return unsafe.compareAndSwapObject(clazz, annotationDataOffset, oldData, newData);
}
private AnnotationData createAnnotationData(int classRedefinedCount) {
Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);
Class<?> superClass = getSuperclass();
Map<Class<? extends Annotation>, Annotation> annotations = null;
if (superClass != null) {
Map<Class<? extends Annotation>, Annotation> superAnnotations =
superClass.annotationData().annotations;
for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) {
Class<? extends Annotation> annotationClass = e.getKey();
if (AnnotationType.getInstance(annotationClass).isInherited()) {
if (annotations == null) { // lazy construction
annotations = new LinkedHashMap<>((Math.max(
declaredAnnotations.size(),
Math.min(12, declaredAnnotations.size() + superAnnotations.size())
) * 4 + 2) / 3
);
}
annotations.put(annotationClass, e.getValue());
}
}
}
if (annotations == null) {
// no inherited annotations -> share the Map with declaredAnnotations
annotations = declaredAnnotations;
} else {
// at least one inherited annotation -> declared may override inherited
annotations.putAll(declaredAnnotations);
}
return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount);
}
获取类本身的 declaredAnnotations
获取父类的 annotations
将 declaredAnnotations+annotations 整合,返回
public static Object parseMemberValue(Class<?> var0, ByteBuffer var1, ConstantPool var2, Class<?> var3) {
Object var4 = null;
byte var5 = var1.get();
switch(var5) {
case 64:
var4 = parseAnnotation(var1, var2, var3, true);
break;
case 91:
return parseArray(var0, var1, var2, var3);
case 99:
var4 = parseClassValue(var1, var2, var3);
break;
case 101:
return parseEnumValue(var0, var1, var2, var3);
default:
var4 = parseConst(var5, var1, var2);
}
if (!(var4 instanceof ExceptionProxy) && !var0.isInstance(var4)) {
var4 = new AnnotationTypeMismatchExceptionProxy(var4.getClass() + "[" + var4 + "]");
}
return var4;
}
public static Annotation annotationForMap(final Class<? extends Annotation> var0, final Map<String, Object> var1) {
return (Annotation)AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
public Annotation run() {
return (Annotation)Proxy.newProxyInstance(var0.getClassLoader(), new Class[]{var0}, new AnnotationInvocationHandler(var0, var1));
}
});
}
class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private static final long serialVersionUID = 6182022883658399397L;
// 保存了当前注解的类型
private final Class<? extends Annotation> type;
// 保存了注解的成员属性的名称和值的映射,注解成员属性的名称实际上就对应着接口中抽象方法的名称
private final Map<String, Object> memberValues;
private transient volatile Method[] memberMethods = null;
AnnotationInvocationHandler(Class<? extends Annotation> var1, Map<String, Object> var2) {
Class[] var3 = var1.getInterfaces();
if (var1.isAnnotation() && var3.length == 1 && var3[0] == Annotation.class) {
this.type = var1;
this.memberValues = var2;
} else {
throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
}
}
public Object invoke(Object var1, Method var2, Object[] var3) {
// 获取当前执行的方法名称
String var4 = var2.getName();
Class[] var5 = var2.getParameterTypes();
if (var4.equals("equals") && var5.length == 1 && var5[0] == Object.class) {
return this.equalsImpl(var3[0]);
} else if (var5.length != 0) {
throw new AssertionError("Too many parameters for an annotation method");
} else {
byte var7 = -1;
switch(var4.hashCode()) {
case -1776922004:
if (var4.equals("toString")) {
var7 = 0;
}
break;
case 147696667:
if (var4.equals("hashCode")) {
var7 = 1;
}
break;
case 1444986633:
if (var4.equals("annotationType")) {
var7 = 2;
}
}
switch(var7) {
case 0:
return this.toStringImpl();
case 1:
return this.hashCodeImpl();
case 2:
return this.type;
default:
// 利用方法名称从memberValues获取成员属性的赋值
Object var6 = this.memberValues.get(var4);
if (var6 == null) {
throw new IncompleteAnnotationException(this.type, var4);
} else if (var6 instanceof ExceptionProxy) {
throw ((ExceptionProxy)var6).generateException();
} else {
// 这一步就是注解成员属性返回值获取的实际逻辑
// 需要判断是否是数组,如果是数组需要克隆一个数组
// 不是数组直接返回
if (var6.getClass().isArray() && Array.getLength(var6) != 0) {
var6 = this.cloneArray(var6);
}
return var6;
}
}
}
}
...
}
通过 Java 系统属性设置:
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");。通过 -D 参数指定,参数是:
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true。
@RateLimit(value = 666)
public class RateLimitMain {
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
RateLimit rateLimit = RateLimitMain.class.getAnnotation(RateLimit.class);
System.out.println(rateLimit.value());
}
}
public final class $Proxy1 extends Proxy implements RateLimit {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m0;
private static Method m3;
public $Proxy1(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
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 Class annotationType() throws {
try {
return (Class)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
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 int value() throws {
try {
return (Integer)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.riemann.springbootdemo.annotation.RateLimit").getMethod("annotationType");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("com.riemann.springbootdemo.annotation.RateLimit").getMethod("value");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。
喜欢的话,点赞、再看、分享三连。
点个在看你最好看
评论