java源码分析-注解AnnotatedElement接口

java源码分析-注解AnnotatedElement接口

概述

在我们讲解注解的运行时处理器时写过这样一段代码:

 //通过Class对象拿到getPersonInfo方法对象Method
Method method = clazz.getDeclaredMethod("getPersonInfo", null);
System.out.println(method.getName());
//根据Method获取到该方法上的注解
MyPersonAnnotation declaredAnnotations = method.getDeclaredAnnotation(MyPersonAnnotation.class);
System.out.println(declaredAnnotations);

​ 其中通过调用Method对象的getAnnotation(MyPersonAnnotation.class)获取该方法上的注解信息,这是典型的通过反射来获取信息的。有个问题,注解和反射是怎么关联上的呢?

​ 其实先要弄明白其中的原理,关键点就在AnnotatedElement接口中。AnnotatedElement接口表示当前运行的虚拟机中一个可以被注解的元素,它提供了一些抽象方法,允许通过反射读取到被注解的元素上的注解信息。

​ 我们看一下这个接口的类图:

java源码分析-注解AnnotatedElement接口

通过上图我们知道:

子接口

  • AnnotatedType:被注解的类型;
  • AnnotatedTypeVariable:被注解的类型变量;
  • AnnotatedArrayType:被注解的数组类型;
  • AnnotatedParamerizedType:被注解的参数化类型;
  • AnnotatedWildcardType:被注解的通配类型;
  • GenericDeclaration:通用声明,用于表示声明类型元素,如:类、方法、构造器等;

实现类

  • AccessibleObject:可访问的对象,如:方法、构造器、属性等;
  • Class:类;
  • Constructor:构造器;
  • Executable:可执行的,如构造器和方法;
  • Field:字段属性;
  • Method:方法;
  • Package:包;
  • Parameter:参数;

方法

AnnotatedElement源码如下:

public interface AnnotatedElement {
    
    default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

   
    <T extends Annotation> T getAnnotation(Class<T> annotationClass);

    
    Annotation[] getAnnotations();

   
    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
         /*
          * Definition of associated: directly or indirectly present OR
          * neither directly nor indirectly present AND the element is
          * a Class, the annotation type is inheritable, and the
          * annotation type is associated with the superclass of the
          * element.
          */
         T[] result = getDeclaredAnnotationsByType(annotationClass);

         if (result.length == 0 && // Neither directly nor indirectly present
             this instanceof Class && // the element is a class
             AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
             Class<?> superClass = ((Class<?>) this).getSuperclass();
             if (superClass != null) {
                 // Determine if the annotation is associated with the
                 // superclass
                 result = superClass.getAnnotationsByType(annotationClass);
             }
         }

         return result;
     }

    
    default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
         // Loop over all directly-present annotations looking for a matching one
         for (Annotation annotation : getDeclaredAnnotations()) {
             if (annotationClass.equals(annotation.annotationType())) {
                 // More robust to do a dynamic cast at runtime instead
                 // of compile-time only.
                 return annotationClass.cast(annotation);
             }
         }
         return null;
     }

    
    default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        Objects.requireNonNull(annotationClass);
        return AnnotationSupport.
            getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).
                                            collect(Collectors.toMap(Annotation::annotationType,
                                                                     Function.identity(),
                                                                     ((first,second) -> first),
                                                                     LinkedHashMap::new)),
                                            annotationClass);
    }

    
    Annotation[] getDeclaredAnnotations();
}

(1)isAnnotationPresent方法

default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

如果指定类型的注解出现在当前元素上,则放回true,否则将返回false;注意defalut关键字,使得接口中的方法可以有一些默认的实现。

(2)getAnnotation方法:

<T extends Annotation> T getAnnotation(Class<T> annotationClass);

如果在当前元素上存在参数所指定类型(annotationClass)的注解,则返回对应的注解,否则将返回null。

(3)getAnnotations方法

Annotation[] getAnnotations();

用于获取这个元素上的所有注解,并以数组形式放回。如果该元素上没有注解,那么将返回一个长度为0的数组。

调用该方法获取到的数组可以*地修改,并且不会对返回给其他调用者的数组产生影响。

(4)getAnnotationsByType方法

default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
         
         T[] result = getDeclaredAnnotationsByType(annotationClass);

         if (result.length == 0 && // Neither directly nor indirectly present
             this instanceof Class && // the element is a class
             AnnotationType.getInstance(annotationClass).isInherited()) { // Inheritable
             Class<?> superClass = ((Class<?>) this).getSuperclass();
             if (superClass != null) {
                 // Determine if the annotation is associated with the
                 // superclass
                 result = superClass.getAnnotationsByType(annotationClass);
             }
         }

         return result;
     }

获取与该元素相关联的注解。如果没有与此元素相关联的注解,则返回值是长度为0的数组。这个方法与getAnnotation(Class)的区别在于,该方法检测其参数是否为可重复的注解类型(也就是是否被@Repeatable),如果是,则尝试通过“looking through”容器注解来查找该类型的一个或多个注解。

(5)getDeclaredAnnotation方法

default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
         // Loop over all directly-present annotations looking for a matching one
         for (Annotation annotation : getDeclaredAnnotations()) {
             if (annotationClass.equals(annotation.annotationType())) {
                 // More robust to do a dynamic cast at runtime instead
                 // of compile-time only.
                 return annotationClass.cast(annotation);
             }
         }
         return null;
     }

获取直接出现在这个元素上的注解。这种方法忽略了继承的注解。如果在此元素上没有直接存在的注解,则返回值是长度为0的数组。

上一篇:二(二)、基于注解形式配置bean


下一篇:Java-注解