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接口表示当前运行的虚拟机中一个可以被注解的元素,它提供了一些抽象方法,允许通过反射读取到被注解的元素上的注解信息。
我们看一下这个接口的类图:
通过上图我们知道:
子接口
- 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的数组。