一文读懂注解的底层原理

点击上方老周聊架构关注我
一、前言
注解类型声明中的标识符指定了注解类型的名称。
如果注解类型与它的任何封闭类或接口具有相同的简单名称,则编译时会出现错误。
每个注解类型的直接父接口都是 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.classClassfile /Users/Riemann/Code/spring-boot-demo/target/classes/com/riemann/springbootdemo/annotation/RateLimit.classLast modified 2021-3-23; size 495 bytesMD5 checksum 1ce59bd6cc4c7297e8d3f032320b04d3Compiled from "RateLimit.java"public interface com.riemann.springbootdemo.annotation.RateLimit extends java.lang.annotation.Annotationminor version: 0major version: 52flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATIONConstant 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: ()Iflags: ACC_PUBLIC, ACC_ABSTRACTAnnotationDefault: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 calledprivate 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 instancefinal 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 loopAnnotationData annotationData = this.annotationData;int classRedefinedCount = this.classRedefinedCount;if (annotationData != null &&annotationData.redefinedCount == classRedefinedCount) {return annotationData;}// null or stale annotationData -> optimistically create new instanceAnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);// try to install itif (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {// successfully installed new AnnotationDatareturn 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 constructionannotations = 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 declaredAnnotationsannotations = declaredAnnotations;} else {// at least one inherited annotation -> declared may override inheritedannotations.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后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。
喜欢的话,点赞、再看、分享三连。

点个在看你最好看
评论



