java注解的实现原理

使用

复制@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
  String value();
}

Target 是 java 中的源注解,标识注解的使用位置,如类,方法,参数,变量等。
Retention 也是源注解,标识注解的作用范围,编译期,运行期。

复制@Log("hello")
public class User {
}
复制public class Client {
  public static void main(String[] args) {
    Log log = User.class.getAnnotation(Log.class);
    System.out.println(log.value());
  }
}

结果为

复制hello

原理

注解本质上是一个接口,

复制public interface Log
    extends Annotation{
    public abstract String value();
}

接下来我们跟一下 getAnnotation 方法的实现原理,

复制public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);
	// 关键就是 annotationData() 方法的实现
        return (A) annotationData().annotations.get(annotationClass);
    }

从类上获取注解对象

复制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
// 看一下 java 是如何创建注解的数据的
            AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);
            // try to install it
            if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {
                // successfully installed new AnnotationData
                return newAnnotationData;
            }
        }
    }

Class 内部对注解数据是使用了缓存的,只会解析一次。

复制private AnnotationData createAnnotationData(int classRedefinedCount) {
// 这两个方法都是 native 方法
        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);
    }

IDE 在 debug 过程中,可以看到

declaredAnnotations 变量是一个 map,key 是注解接口的 class,value 是接口的一个动态代理实现,具体的处理是 AnnotationInvocationHandler,

package sun.reflect.annotation;

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;
}
}

  <span class="hljs-keyword">switch</span>(var7) {
  <span class="hljs-keyword">case</span> <span class="hljs-number">0</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.toStringImpl();
  <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.hashCodeImpl();
  <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.type;
  <span class="hljs-keyword">default</span>:

// 核心逻辑
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);
}

      <span class="hljs-keyword">return</span> var6;
    }
  }
}

}
}

通过 debug 信息可以看到,注解的信息是保存在 AnnotationInvocationHandler 的 memberValues 变量中的,调用 value 方法是,会代理到 invoke 方法中,数据从 memberValues 变量中取。