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

      switch(var7) {
      case 0:
        return this.toStringImpl();
      case 1:
        return this.hashCodeImpl();
      case 2:
        return this.type;
      default:
// 核心逻辑
        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;
        }
      }
    }
  }
}

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

posted @ 2020-07-11 10:35  strongmore  阅读(4138)  评论(0编辑  收藏  举报